How to create a duplicate of the existing User model which display objects only if a condition is satisfied?
Here in this pic, pending users should show all the users with is_active = True:
In the documentation, there was a similar statement:
pendinguser = models.ForeignKey(User, limit_choices_to={'is_staff': True})
How and where to add this to make this work?
See this example:
you have your user model 'User'
Now create a new model and inherit User model like this
class ProxyUser(User):
objects = ProxyUserManagaer()
class Meta:
proxy = True
Now create you custom definition of this Proxy model in manager function:
class ProxyUserManager(models.Manager):
def get_queryset(self):
return super(FeatureManager, self).get_queryset().filter(<add your custom definiton her>)
Related
New to Django and relational DBs. I'm building the classic Doctor appointment booking app and have come to a point where I don't know what to do. I've created the Doctor model pointing to a Clinic, but in my API the Clinic model won't show a list of all Doctors. How could I achieve this?
class Clinic(models.Model):
name = models.CharField(max_length=200)
class Doctor(models.Model):
clinic = models.ManyToManyField(Clinic, related_name="doctors")
class ClinicSerializer(serializers.ModelSerializer):
class Meta:
model = Clinic
fields = '__all__'
class DoctorSerializer(serializers.ModelSerializer):
class Meta:
model = Doctor
fields = '__all__'
class ClinicViewset(viewsets.ModelViewSet):
queryset = Clinic.objects.all()
serializer_class = ClinicSerializer
class DoctorViewset(viewsets.ModelViewSet):
queryset = Doctor.objects.all()
serializer_class = DoctorSerializer
Django will automatically create the link from Clinic to Doctor. You don't need to (shouldn't) define it. From the docs:
Django also creates API accessors for the “other” side of the relationship – the link from the related model to the model that defines the relationship. For example, a Blog object b has access to a list of all related Entry objects via the entry_set attribute: b.entry_set.all().
The related_name argument that you passed to ManyToManyField when you created the clinic field is the name of the relation from Clinic to Doctor. It is optional and if you didn't pass it, it would be the lower-cased named of the model + _set - doctor_set in your case.
Usually you would set it to a plural in the case of ManyToManyField. In your case: doctors.
Because you have related_name="doctor" currently, you can retrieve a clinic's doctors with: clinic.doctor.all().
I wanna change all fields of a json object except 'pk' in DRF. I just need to keep one json data. When adding a new data ,this one should override existing data. Is there a way to do it with django ?
my models.py
class ClientUser2(models.Model):
phone_number = models.CharField(max_length=20,unique=True)
name = models.CharField(max_length=100,blank=True)
status = models.IntegerField(default=1)
class ClientNameSerializer(serializers.HyperlinkedModelSerializer):
class Meta:
model = ClientUser2
fields = ('url','phone_number','name','status','pk')
my views.py
class ClientViewSet(viewsets.ModelViewSet):
"""
API endpoint that allows messages to be viewed or edited.
"""
queryset = ClientUser2.objects.all()
serializer_class = ClientNameSerializer
and it's my api root
api_root
If you want to be able to only retrieve and update models you can use RetrieveUpdateApiView
Reference : https://www.django-rest-framework.org/api-guide/generic-views/#retrieveupdateapiview
I am writing tests for a large Django application with multiple apps. As part of this process I am gradually creating factories for all models of the different apps within the Django project.
However, I've run into some confusing behavior with FactoryBoy
Our app uses Profiles which are linked to the default auth.models.User model with a OneToOneField
class Profile(models.Model):
user = models.OneToOneField(User)
birth_date = models.DateField(
verbose_name=_("Date of Birth"), null=True, blank=True)
( ... )
I created the following factories for both models:
#factory.django.mute_signals(post_save)
class ProfileFactory(factory.django.DjangoModelFactory):
class Meta:
model = profile_models.Profile
user = factory.SubFactory('yuza.factories.UserFactory')
birth_date = factory.Faker('date_of_birth')
street = factory.Faker('street_name')
house_number = factory.Faker('building_number')
city = factory.Faker('city')
country = factory.Faker('country')
avatar_file = factory.django.ImageField(color='blue')
tenant = factory.SubFactory(TenantFactory)
#factory.django.mute_signals(post_save)
class UserFactory(factory.django.DjangoModelFactory):
class Meta:
model = auth_models.User
username = factory.Faker('user_name')
first_name = factory.Faker('first_name')
last_name = factory.Faker('last_name')
email = factory.Faker('email')
is_staff = False
is_superuser = False
is_active = True
last_login = factory.LazyFunction(timezone.now)
profile = factory.RelatedFactory(ProfileFactory, 'user')
Which I then run the followings tests for:
class TestUser(TestCase):
def test_init(self):
""" Verify that the factory is able to initialize """
user = UserFactory()
self.assertTrue(user)
self.assertTrue(user.profile)
self.assertTrue(user.profile.tenant)
class TestProfile(TestCase):
def test_init(self):
""" Verify that the factory is able to initialize """
profile = ProfileFactory()
self.assertTrue(profile)
All tests in TestUser pass, but the TestProfile fails on the factory initialization ( profile = ProfileFactory()) and raises the following error:
IntegrityError: duplicate key value violates unique constraint "yuza_profile_user_id_key"
DETAIL: Key (user_id)=(1) already exists.
Its not clear to me why a duplicate User would already exist, (there should only be one call to create one right?, especially since any interfering signals have been disabled)
My code was based on the example from the FactoryBoy documentation, which also dealt with Users / Profiles that are connected via a OneToOneKey
Does anyone know what I am doing wrong?
Update
As per the suggestions of both Bruno and ivissani I've changed the user line in the ProfileFactory to
user = factory.SubFactory('yuza.factories.UserFactory', profile=None)
Now all the tests described above pass successfully!
However I still run into the following issue - when other factories call the UserFactory the
IntegrityError: duplicate key value violates unique constraint "yuza_profile_user_id_key"
DETAIL: Key (user_id)=(1) already exists.
still returns.
I've included an example of a factory calling the UserFactory below, buts its happening to every factory that has a user field.
class InvoiceFactory(factory.django.DjangoModelFactory):
class Meta:
model = Invoice
user = factory.SubFactory(UserFactory)
invoice_id = None
title = factory.Faker('catch_phrase')
price_paid = factory.LazyFunction(lambda: Decimal(0))
tax_rate = factory.LazyFunction(lambda: Decimal(1.21))
invoice_datetime = factory.LazyFunction(timezone.now)
Changing the user field on the InvoiceFactory to
user = factory.SubFactory(UserFactory, profile=None)
Helps it pass some of the tests, but eventually runs into trouble since it no longer has a profile associated with it.
Weirdly the following (declaring the user before the factory) DOES work:
self.user = UserFactory()
invoice_factory = InvoiceFactory(user=self.user)
Its not clear to me why I still keep running into the IntegrityError here, calling the UserFactory() now works fine.
I think it's because your ProfileFactory creates a User instance, using the UserFactory which itself tries to create a new Profile instance using the ProfileFactory.
You need to break this cycle, as described in the documentation you link to:
# We pass in profile=None to prevent UserFactory from
# creating another profile (this disables the RelatedFactory)
user = factory.SubFactory('yuza.factories.UserFactory', profile=None)
If this doesn't work for you and you need more advanced handling, then I suggest implementing a post_generation hook where you can do more advanced things.
EDIT:
Another option is to tell Factory Boy to not recreate a Profile if there is already one for the User by using the django_get_or_create option:
#factory.django.mute_signals(post_save)
class ProfileFactory(factory.django.DjangoModelFactory):
class Meta:
model = profile_models.Profile
django_get_or_create = ('user',)
If you do so, you might be able to remove the profile=None that I suggested before.
EDIT 2:
This might also help, change the UserFactory.profile using a post_generation hook:
#factory.django.mute_signals(post_save)
class UserFactory(factory.django.DjangoModelFactory):
class Meta:
model = auth_models.User
...
# Change profile to a post_generation hook
#factory.post_generation
def profile(self, create, extracted):
if not create:
return
if extracted is None:
ProfileFactory(user=self)
EDIT 3
I've just realised that the username field in your UserFactory is different from the one in factroy boy's documentation, and it's unique in Django. I wonder if this doesn't cause some old instances to be reused because the username is the same.
You may want to try changing this field to a sequence in your factory:
#factory.django.mute_signals(post_save)
class UserFactory(factory.django.DjangoModelFactory):
class Meta:
model = auth_models.User
# Change to sequence to avoid duplicates
username = factory.Sequence(lambda n: "user_%d" % n)
So I am just getting familiar with django and django-rest-framework.
I have a model of Jobs that have an owner, and I want to add the list of jobs a user owns to the user endpoint.
I tried to do it like this, as the tutorial of the django rest framework says:
class UserSerializer(serializers.ModelSerializer):
jobs = serializers.PrimaryKeyRelatedField(many = True, queryset = Job.objects.all())
class Meta:
model = User
fields = ('id', 'username', 'jobs')
But for some reason, when I want to view the users, I recieve
AttributeError at /users/
'User' object has no attribute 'jobs'
The documentation about the PrimareyKeyRelatedField looks just like this. Do I maybe have to do something with the user model?
What works is the following:
class UserSerializer(serializers.ModelSerializer):
class Meta:
model = User
fields = ('id', 'username', 'job_set')
but I don't like that solution as I want to have more control about how the list is presented (maybe change the ids to complete json objects or rename the attribut name from 'job_set' to 'job)
I really don't now what I am overseeing...
You can do two things,
jobs = serializers.PrimaryKeyRelatedField(many = True, source='job_set' queryset = Job.objects.all())
or
Set related_name='jobs' attribute to User relational field.
I'll start by explaining the current scenario of my problem.
Models
There are 5 models for example: Community, User, Membership, Reservation, Item
class User(Model):
name = CharField(max_length=50)
communities = ManyToManyField('Community', through='Membership')
class Community(Model):
name = CharField(max_length=50)
class Membership(Model):
user = ForeignKey('User')
community = ForeignKey('Community')
class Item(Model):
name = CharField(max_length=50)
class Reservation(Model):
item = ForeignKey('Item')
membership = ForeignKey('Membership')
Community is m:m User through Membership.
Reservation is 1:m Membership
Item is 1:m Reservation
ModelSerializer
class ReservationSerializer(ModelSerializer):
class Meta:
model = Reservation
fields = ('membership', 'item')
Problem
What's the best approach to automatically set the User value from request.user, hence the attribute that is required for this ReservationSerializer is just the community and item instead of membership and item?
References
How to create a django User using DRF's ModelSerializer
Return the current user with Django Rest Framework
http://www.django-rest-framework.org/tutorial/4-authentication-and-permissions#associating-snippets-with-users
Django Rest Framework ModelSerializer Set attribute on create
Dynamically limiting queryset of related field
djangorestframework: Filtering in a related field
The role of the serializer is to represent the information in a legible way, not to manipulate such data. You may want to do that on a view: Using the generic ListCreateAPIView available on DRF, you could use the pre_save signal to store that information:
from rest_framework.generics import ListCreateAPIView
class ReservationView(ListCreateAPIView):
def pre_save(self, obj):
obj.membership.user = self.request.user