Daviddd
Daviddd

Reputation: 791

model field named url and django rest framework url

I started to use the great django-rest-framework days ago. I'm not able to solve this simple issue.

My model contains a models.URLField named url.

My serializers.py file:

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

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

Checking the API result the field 'url' is populated with model.URLField.

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

Instead I would like to have

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

How can I solve? Thanks

Upvotes: 6

Views: 3882

Answers (6)

focus zheng
focus zheng

Reputation: 380

the above answers are not precise.It is simply to control the name of url(default is 'url') by using the key "url_field_name".

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

the source code of ModelSerializer in serializer.py

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)

Upvotes: 1

kigawas
kigawas

Reputation: 1258

The easiest way to avoid the conflict is to set URL_FIELD_NAME in settings.py like:

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 
}

Upvotes: 2

Eraldo
Eraldo

Reputation: 545

I personally prefer to set the default hyperlinked field to another name altogether.

You can do this via the URL_FIELD_NAME setting.

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

e.g: URL_FIELD_NAME = 'key' (default is 'url')

Upvotes: 4

fercreek
fercreek

Reputation: 147

Nginx needs to be configured correctly, put your ip in the 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;
}

Change http://127.0.0.1:8003 by http://this-is-my-ip-address.com/[port]

Upvotes: -2

Matt Cooper
Matt Cooper

Reputation: 937

The accepted answer didn't work for me in DRF 3. I got my model's url data for both url and url_in_model. To get the correct url value from DRF, it looked like:

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

    class Meta:
        model = Account

account-detail should be replaced with whatever view corresponds to a single Account.

Upvotes: 5

WSV
WSV

Reputation: 116

It may be considered poor form (I am by no means a pro programmer or rest_framework expert), but I believe you can add extra context to the serialized output:

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

Extra fields can correspond to any property or callable on the model.


So in the above the field 'get_absolute_url' must be in the 'Account' model. In your case (I think) you could do this:

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')

Of course you would pick the field type that suits.

I haven't had the chance to test this, so there is the chance that using 'url' as your source causes an issue and you may want to name your model field something else - apologies if that is the case and I have wasted your time.

Hope I have helped.

Upvotes: 9

Related Questions