【问题标题】:Google app engine ReferenceProperty relationshipsGoogle 应用引擎 ReferenceProperty 关系
【发布时间】:2010-11-15 16:04:05
【问题描述】:

我正在尝试使用 ReferenceProperty 让我的模型相关联,但运气不佳。我有 3 个级别:组、主题、优点和缺点。就像在一个小组中包含许多主题一样,每个主题中可能有许多优点和缺点。

我可以很好地存储新组,但我不知道如何在这些组下存储主题。我想从每个组下方带有“新主题”链接的页面链接,这会将它们带到一个简单的表单(目前为 1 个字段)。显然,URL 需要对组的 id 或其他内容进行某种引用。

这是我的模型:

class Groups(db.Model):

    group_user = db.UserProperty()
    group_name = db.StringProperty(multiline=True)
    group_date = db.DateTimeProperty(auto_now_add=True)


class Topics(db.Model):

    topic_user = db.UserProperty()
    topic_name = db.StringProperty(multiline=True)
    topic_date = db.DateTimeProperty(auto_now_add=True)
    topic_group = db.ReferenceProperty(Groups, collection_name='topics')

class Pro(db.Model):

    pro_user = db.UserProperty()
    pro_content = db.StringProperty(multiline=True)
    pro_date = db.IntegerProperty(default=0)
    pro_topic = db.ReferenceProperty(Topics, collection_name='pros')    

class Con(db.Model):

    con_user = db.UserProperty()
    con_content = db.StringProperty(multiline=True)
    con_date = db.IntegerProperty(default=0)
    con_topic = db.ReferenceProperty(Topics, collection_name='cons')    

我想在实际页面中显示组列表,然后在其主题下方显示一个功能:

class Summary(webapp.RequestHandler):
    def get(self):

        groups_query = Groups.all()
        groups = groups_query.fetch(1000)
        template_values = {

            'groups': groups,           
        }

        path = os.path.join(os.path.dirname(__file__), 'summary.html')
        self.response.out.write(template.render(path, template_values))

最后是html:

<html>
  <body>
    <a href="/newgroup">New Group</a>
    <br>
    {% for group in groups %}

    <font size="24">{{ group.group_name|escape }}</font><br> by <b>{{ group.group_user }}</b> at <b>{{ group.group_date }}</b> {{ group.raw_id }}
    <br>
    <a href="/newtopic?id={{group.key.id}}" >New topice </a>
    <br>
    <blockquote>
        {{ topics.topics_name }}
    </blockquote>


    {% endfor %}
  </body>
</html>

【问题讨论】:

    标签: python google-app-engine django-models model django-templates


    【解决方案1】:

    具有副作用的东西,例如更改存储(例如通过创建新对象)应该是 HTTP GET - GET 应该基本上只执行“读取”操作。这不是迂腐,它是 HTTP 语义的关键部分——浏览器、缓存、代理等,被允许作为只读操作对 GET 进行操作(例如,通过缓存结果而不向服务器传递请求,如果它们可以从缓存中满足)。

    对于修改,使用 HTTP 动词,例如 POST(最流行的本质上是因为所有浏览器都正确实现它)或专用操作 PUT(创建新对象)或 DELETE(删除对象)。我假设您将使用 POST 来支持各种浏览器。

    要从浏览器获取 POST,您需要 Javascript 向导或带有 method=post 的普通旧表单——为简单起见,我假设后者。

    如果您使用的是 Django 1.0(应用引擎现在支持该版本),它有自己的机制来制作、验证和接受基于模型的表单。其他框架也有自己类似的高级层。

    如果你想避免“丰富”的框架,你必须为你的 HTML 表单手动实现模板,将它们(通过某种 URL 调度,例如在 app.yaml 中)定向到你的处理程序,使用def post(self):,从请求中获取数据,验证它,形成新对象,放置它,显示一些确认页面。

    您不清楚该程序的哪些部分?您的问题的标题专门针对参考属性,但我不确定它们会给您带来什么特别的问题——从您的问题文本来看,您似乎对它们采取了正确的态度。

    编辑:OP现在在评论中澄清说他的问题是如何制作类似的东西:

    "<a href="/newtopic?id={{group.key.id}}" >New topic </a>" 
    

    工作。有不止一种方法可以做到这一点。如果新主题 URL 由静态表单提供,则该表单的帖子“操作”的处理程序可以通过 Referer: 标头返回到 id=(一个臭名昭著但无法修复的拼写错误),但这有点笨重而脆弱。更好的做法是让一个处理程序为新主题 URI 提供服务,该处理程序的 def get 从请求中获取 id= 并将其插入到生成的表单模板中——例如,在隐藏的输入字段中。让该表单的模板包含(在其他字段中):

    <INPUT TYPE=hidden NAME=thegroupid VALUE={{ theid }}> </INPUT>
    

    theid 放在渲染该模板的上下文中,它将在接收表单的操作的def post 最终获得的请求中。

    【讨论】:

    • 什么?我没有看到他在任何地方这样做,或者询问是否这样做。你的意思是在另一个问题上发布这个?
    • @Nick,问题不清楚——以防&lt;a href= 旨在直接导致主题创建,我警告不要这样做(现在 OP 澄清它正确地导致发布表单) .你也很难理解这个问题(尽管看起来至少你的答案确实引起了一些澄清),那么为什么要否决一个试图确保在模棱两可的情况下触及所有基础的广谱答案呢?
    • 嗯,一个隐藏的表单项——简洁的解决方案。不过,我仍然不明白如何正确使用数据存储。因此,假设我有组的 id,并将其解析为 NewTopicSubmit(您可以在上面看到它 - 与 NewGroupSubmit 相同的形式)类;你如何设置关系?我需要使用 topic.topic_group =.... id 之类的东西?没有掌握这一点,感觉自己像个白痴>
    • 引用值是被引用实体的key;一旦你有了组对象 grp,newtopic.topic_group = grp.key() 就是在newtopic.put() 之前需要发生的事情,尽管你可以只做newtopic.topic_group = grp,它会代表你获取密钥。所以最好直接传递密钥(“字符串编码的密钥是一个不透明的值,使用可安全包含在 URL 中的字符......可以通过将其传递给 Key 构造函数(编码参数)." 根据code.google.com/appengine/docs/python/datastore/keyclass.html
    • ...当然 Key.from_path 允许您从实体类型、父级[s](如果有)和 ID 构建密钥。
    【解决方案2】:

    只是为了回答其他人的问题,您可能已经想到了这一点:

    类新主题(webapp.RequestHandler): 定义获取(自我): groupId = self.request.get('group') # 从数据库中获取实际的组对象并使用 topic_group=object 初始化主题,如 'Nick Johnson's answer 中所示,或者执行以下操作 主题 = 主题() topic.name = self.request.get("topicname") topic.reference = groupId 主题.put()

    【讨论】:

      【解决方案3】:

      谢谢你的回复。

      是的,我知道 get vs post。我发布的课程只是为了实际打印所有 Groups()。

      我的问题是我不确定如何使用模型以一种分层方式保存数据,即 Groups > Topics > Pros/Cons。

      抓取数据很简单,我正在使用:

      class NewGroupSubmit(webapp.RequestHandler):
          def post(self):
      
              group = Groups()
              if users.get_current_user():
                  group.group_user = users.get_current_user()     
              group.group_name = self.request.get('groupname')
      
              group.put()
              self.redirect('/summary')
      

      我需要另一个函数来添加一个新主题,将其存储在该组中。例如,假设一个组是“汽车”;主题可能是“法拉利”、“保时捷”、“宝马”,然后是每个主题的优缺点。我意识到我有点含糊不清,但这是因为我对关系数据库非常陌生,并且不太习惯这些术语。

      【讨论】:

        【解决方案4】:

        我不太确定您遇到了什么问题。您列出的所有内容看起来都很好 - ReferenceProperties 是根据您对描述的期望进行设置的。我能看到的唯一问题是,在你的模板中,你指的是一个变量“主题”,它没有在任何地方定义,你也没有在任何地方迭代一个组的主题。你可以这样做:

        <html>
          <body>
            <a href="/newgroup">New Group</a>
            <br>
            {% for group in groups %}
        
            <font size="24">{{ group.group_name|escape }}</font><br> by <b>{{ group.group_user }}</b> at <b>{{ group.group_date }}</b> {{ group.raw_id }}
            <br>
            <a href="/newtopic?id={{group.key.id}}" >New topice </a>
            <br>
            Topics:
            <ul>
              {% for topic in group.topics %}
                <li>{{topic.topic_name}}</li>
              {% endfor %}
            </ul>
            {% endfor %}
          </body>
        </html>
        

        要创建一个新主题,只需使用构造函数,传入所需的参数:

        mytopic = Topic(topic_name="foo", topic_group=somegroup)
        

        这里,somegroup 应该是 Group 对象,或者是 Group 对象的键。

        【讨论】:

        • 是的,我知道我可以做到,但我不确定我的新主题的帖子功能是什么。如何写入数据存储以便主题有一个组。你可以看到我的尝试:“New topice " 但我认为这与它没有任何关系,因为我显然需要以某种方式将其传递给函数。
        • 这个更新有帮助吗?不过,您确实需要在最初的问题中澄清您的问题。
        猜你喜欢
        • 2012-06-21
        • 1970-01-01
        • 2011-02-04
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2013-08-30
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多