简体   繁体   中英

Foreign key field not POSTing on Django REST

So, i'm doing an API for a to-do task manager, and in this api i have a lot of tables that are related to one another (a Project belongs to a Client, a Client is a Person that belongs to a City, and so on) and i hope that by learning how to fix the example below, i'll be able to fix the rest of the tables, that have a similar problem.

My problem is: a Person belongs to a City (that already exists), so one of the fields of Person is a ForeignKey to City, that i believe should be a Integer, the city id (Person lives in 1 city, City can home N people).

But i can't get it to work.

On the django /admin site, it all works perfectly. I can create the Person with his info and theres a select box with a list of every City and it works great.

But when i try to POST using Postman or even the /api site, there used to be no field for the City id, now after googling and trying everything, i somehow added the City id field, but can't get it to work.

The current problem is "Cannot asign '8' (the city id): ...must be a "City" instance.

I have set the default to 1 but that doesn't solve the problem, seen that the problem is the same on other tables (Project has a Client FK, Client has Person FK, etc.).

Do you guys have any ideia of why that happens? I've googled, watched and read guides on similar stuff but can't get it right.

Here are my files:

Models.py

class City(models.Model):
    idcity = models.AutoField(primary_key=True)
    name = models.CharField(max_length=100, blank=True, null=True)
    uf = models.CharField(max_length=2, blank=True, null=True)

    def __str__(self):
        return (self.name + " - " + self.uf)

    class Meta:
        managed = False
        db_table = 'city'
        verbose_name = 'City'
        verbose_name_plural = 'Cities'

class Person(models.Model):
    idperson = models.AutoField(primary_key=True)
    name = models.CharField(max_length=200, blank=True, null=True)
    phone = models.CharField(max_length=15, blank=True, null=True)
    address = models.CharField(max_length=500, blank=True, null=True)
    email = models.CharField(max_length=200, blank=True, null=True)
    idcity = models.ForeignKey('City', on_delete=models.DO_NOTHING, db_column='idcity', blank=True, null=True, default=1)

    def __str__(self):
        return '{}'.format(self.name)

    class Meta:
        managed = False
        db_table = 'person'
        verbose_name = 'Person'
        verbose_name_plural = 'People'

Serializers.py


class CityDetailSerializer(ModelSerializer):
    idcity = serializers.IntegerField(required=False)
    class Meta:
        model = City
        fields = [
            'idcity ',
            'name',
            'uf',
        ]
        depth = 4


class PersonDetailSerializer(ModelSerializer):
    # name = serializers.CharField()
    # phone = serializers.CharField()
    # address = serializers.CharField()
    # email = serializers.CharField()
    # idcity = serializers.IntegerField()
    idcity = CityDetailSerializer()

    class Meta:
        model = Person
        fields = '__all__'
        depth=2

Views.py

tbh i dont know why my parter used so many views, but ok

class CityListAPIView(ListAPIView):
    queryset = City.objects.all()
    serializer_class = CityListSerializer

class CityDetailAPIView(RetrieveAPIView):
    queryset = City.objects.all()
    serializer_class = CityDetailSerializer

# i tried commenting and uncommenting the following
# but it still doesnt work

    def get(self, request, pk=None):
        if pk:
            city = get_object_or_404(City.objects.all(), pk=int(pk))
            serializer = CityDetailSerializer(city)
            return Response(serializer.data)
        cities = City.objects.all()
        serializer = CityDetailSerializer(cities, many=True)
        return Response(serializer.data)

class CityCreateAPIView(CreateAPIView):
    queryset = City.objects.all()
    serializer_class = CityDetailSerializer

class CityUpdateAPIView(UpdateAPIView):
    queryset = City.objects.all()
    serializer_class = CityDetailSerializer

class CityDeleteAPIView(DestroyAPIView):
    queryset = City.objects.all()
    serializer_class = CityDetailSerializer



class PeopleListAPIView(ListAPIView):
    queryset = Person.objects.all()
    serializer_class = PersonListSerializer

class PersonDetailAPIView(RetrieveAPIView):
    queryset = Person.objects.all()
    serializer_class = PersonDetailSerializer

    def get(self, request, pk=None):
        if pk:
            person = get_object_or_404(Person.objects.all(), pk=pk)
            serializer = PersonDetailSerializer(person)
            return Response(serializer.data)
        people = Person.objects.all()
        serializer = PersonDetailSerializer(people, many=True)
        return Response(serializer.data)

class PersonCreateAPIView(CreateAPIView):
    queryset = Person.objects.all()
    serializer_class = PersonDetailSerializer

class PersonUpdateAPIView(UpdateAPIView):
    queryset = Person.objects.all()
    serializer_class = PersonDetailSerializer

class PersonDeleteAPIView(DestroyAPIView):
    queryset = Person.objects.all()
    serializer_class = PersonDetailSerializer

URLs.py

    path('cities/', CityListAPIView.as_view()),
    path('cities/create', CityCreateAPIView.as_view()),
    url(r'^cities/(?P<pk>[0-9]+)/$', CityDetailAPIView.as_view()),
    url(r'^cities/(?P<pk>[0-9]+)/edit/$', CityUpdateAPIView.as_view()),
    url(r'^cities/(?P<pk>[0-9]+)/delete/$', CityDeleteAPIView.as_view()),

    path('people/', PeopleListAPIView.as_view()),
    path('people/create', PersonCreateAPIView.as_view()),
    url(r'^people/(?P<pk>[0-9]+)/$', PersonDetailAPIView.as_view()),
    url(r'^people/(?P<pk>[0-9]+)/edit/$', PersonUpdateAPIView.as_view()),
    url(r'^people/(?P<pk>[0-9]+)/delete/$', PersonDeleteAPIView.as_view()),

If you need any more code or information please ask, i really need help, since im completely new a Django and need this to pass this college assignment.

Thank you anyway!

How i fixed it:

I added the following function, that i found in some other question. Thanks to the guy who responded with it.

views.py

class PersonCreateAPIView(CreateAPIView):
#    ...    
    def perform_create(self, serializer):
        city = get_object_or_404(City, idcity=self.request.data.get('idcity'))
        return serializer.save(idcity=city)

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM