【问题标题】:model field named url and django rest framework url模型字段名为 url 和 django rest 框架 url
【发布时间】:2013-08-14 12:33:57
【问题描述】:

几天前我开始使用很棒的 django-rest-framework。 我无法解决这个简单的问题。

我的模型包含一个名为 url 的 models.URLField。

我的 serializers.py 文件:

class ModelSerializer(serializers.HyperlinkedModelSerializer):
    owner = serializers.Field(source='owner.username')    

    class Meta:
        model = Model
        fields = ('url', 'owner', 'title', 'abstract', 'category', 'position', 'param1')

检查 API 结果,字段 'url' 填充有 model.URLField。

"results": [
        {
            "url": "http://www.web.com", 
            "owner": "me", 
            "title": "title of the stuff"
        }

相反,我想拥有

"results": [
        {
            "url": "http://localhost:8000/en/apiv1/maps/4/", 
            "url_in_model": "http://www.web.com", 
            "owner": "me", 
            "title": "Forest fire"
        }

我该如何解决? 谢谢

【问题讨论】:

  • Ummm....重命名你的模型字段?
  • 我知道,但不太可行。我想将此作为最后的选择。想法?
  • 很遗憾,您可能别无选择。如果使用 django-rest 的好处超过了必须稍微更改模型字段名称的不便,那么我会更改名称。您始终可以将字段的标签显示为“Url”,而不是您可能将其更改为的任何内容。
  • 感谢您的回复。我会按照你的建议去做。

标签: django django-rest-framework


【解决方案1】:

它可能被认为是糟糕的形式(我绝不是专业程序员或 rest_framework 专家),但我相信您可以为序列化输出添加额外的上下文:

http://django-rest-framework.org/api-guide/serializers.html#specifying-fields-explicitly


class AccountSerializer(serializers.ModelSerializer):
    url = serializers.CharField(source='get_absolute_url', read_only=True)
    groups = serializers.PrimaryKeyRelatedField(many=True)

    class Meta:
        model = Account

额外字段可以对应于模型上的任何属性或可调用对象。


所以在上面的字段“get_absolute_url”必须在“帐户”模型中。 在你的情况下(我认为)你可以这样做:

class ModelSerializer(serializers.HyperlinkedModelSerializer):
    owner = serializers.Field(source='owner.username')
    url_in_model = serializer.Field(source='url')    

    class Meta:
        model = Model
        fields = ('url', 'url_in_model', 'owner', 'title', 'abstract', 'category', 'position', 'param1')

当然你会选择适合的字段类型。

我还没有机会对此进行测试,因此使用“url”作为您的来源可能会导致问题,您可能希望将您的模型字段命名为其他名称 - 如果是这种情况,我深表歉意浪费了你的时间。

希望我有所帮助。

【讨论】:

    【解决方案2】:

    接受的答案在 DRF 3 中对我不起作用。我得到了我的模型的 url 数据 urlurl_in_model。要从 DRF 中获取正确的 url 值,它看起来像:

    class AccountSerializer(serializers.ModelSerializer):
        url = serializers.HyperlinkedIdentityField(view_name='account-detail')
        url_in_model = serializer.URLField(source='url')  
    
        class Meta:
            model = Account
    

    account-detail 应替换为与单个帐户对应的任何视图。

    【讨论】:

      【解决方案3】:

      我个人更喜欢将默认超链接字段设置为另一个名称。

      您可以通过URL_FIELD_NAME 设置来做到这一点。

      来源:http://www.django-rest-framework.org/api-guide/serializers/#changing-the-url-field-name

      例如:URL_FIELD_NAME = 'key'(默认为 'url')

      【讨论】:

        【解决方案4】:

        避免冲突的最简单方法是在settings.py 中设置URL_FIELD_NAME 像:

        REST_FRAMEWORK = {
            "DEFAULT_AUTHENTICATION_CLASSES": [
                "rest_framework.authentication.SessionAuthentication",
                "rest_framework.authentication.BasicAuthentication",
            ],
            "DEFAULT_PERMISSION_CLASSES": ["rest_framework.permissions.IsAuthenticated"],
            "URL_FIELD_NAME": "api_url", // <---- add this 
        }
        

        【讨论】:

          【解决方案5】:

          上面的答案并不准确,只是简单地通过“url_field_name”键来控制url的名称(默认为'url')。

          class UserSerializer(serializers.ModelSerializer):
             url_field_name='test-url'
             class Meta:
                 model = UserInfo
                 extra_kwargs = {
                  'test-url': {
                      'view_name': '<your view name defined on urls.py>',
                      'lookup_field': '<lookup_field>',
                      'lookup_url_kwarg': '<lookup_url_kwarg>'
                    }
                 }
                 fields = ['test-url']  #remember include your defined url name
          

          serializer.py中ModelSerializer的源码

          def get_fields(self):
              """
              Return the dict of field names -> field instances that should be
              used for `self.fields` when instantiating the serializer.
              """
              if self.url_field_name is None:
                  self.url_field_name = api_settings.URL_FIELD_NAME
          
              assert hasattr(self, 'Meta'), (
                  'Class {serializer_class} missing "Meta" attribute'.format(
                      serializer_class=self.__class__.__name__
                  )
              )
              assert hasattr(self.Meta, 'model'), (
                  'Class {serializer_class} missing "Meta.model" attribute'.format(
                      serializer_class=self.__class__.__name__
                  )
              )
              if model_meta.is_abstract_model(self.Meta.model):
                  raise ValueError(
                      'Cannot use ModelSerializer with Abstract Models.'
                  )
          
              declared_fields = copy.deepcopy(self._declared_fields)
              model = getattr(self.Meta, 'model')
              depth = getattr(self.Meta, 'depth', 0)
          

          【讨论】:

            【解决方案6】:

            Nginx需要正确配置,把你的ip放在PROXY_PASS中

            location / {
                    proxy_pass http://127.0.0.1:8003;
                    proxy_set_header X-Forwarded-Host $server_name;
                    proxy_set_header X-Real-IP $remote_addr;
            }
            

            http://127.0.0.1:8003 更改为http://this-is-my-ip-address.com/[port]

            【讨论】:

              猜你喜欢
              • 1970-01-01
              • 1970-01-01
              • 1970-01-01
              • 1970-01-01
              • 2015-01-17
              • 2015-06-06
              • 1970-01-01
              • 1970-01-01
              • 2016-01-29
              相关资源
              最近更新 更多