Is it possible to get model's field as object
For example:
I have this model
class User(models.Model):
name = models.CharField(max_length=255)
email = models.TextField(blank=True)
phone = models.TextField(blank=True)
now I want to use the field as object
I want to be able to do this
def update_a_field(field):
model_field = field
query_set = User.objects.values(field.__name__).filter(field__isnull=False)
then I can call my function like this
name = User._meta.get_field("name")
update_a_field(name)
email = User._meta.get_field("email")
update_a_field(email)
This should work:
def update_a_field(field):
model_field = field
filter_data = { "{}__isnull".format(field.__name__) : False}
query_set = User.objects.values(field.__name__).filter(**filter_data)
Related
I have a User model,
class User(AbstractBaseUser):
id = models.IntegerField(primary_key=True)
email = models.EmailField(unique=True)
I have another model named Company. The Company model has a reference to User model via an Integer field.
class Company(models.Model):
user_id = models.IntegerField(db_index=True)
name = models.CharField(max_length=100)
size = models.IntegerField(default=1)
I wanted to extract the company information along with user information.
basically I want a user object dictionary like this {'id':1, 'email':'abc#gmail.com','name':'foobar.co','size':400}
I want to annotate the user objects with name and size. As of now, I tried in the serializer's to_representation method. However, for millions of users this is super slow.
class UserSerializer(serializers.Serializer):
id = serializers.IntegerField(read_only=True)
email = serializers.EmailField(read_only=True)
def to_representation(self, instance):
response = super(UserSerializer, self).to_representation(instance)
company = Company.objects.filter(user_id=instance.id)
if company.exists():
company = company.first()
response['name'] = company.name
response['size'] = company.size
return response
How can I achieve this annotation in the query itself.
If the links in the comment do not help you, You can use SerializerMethodField for name, and size
class UserSerializer(serializers.Serializer):
id = serializers.IntegerField(read_only=True)
email = serializers.EmailField(read_only=True)
name = serializers.SerializerMethodField()
size = serializers.SerializerMethodField()
def get_name(self, obj):
# get name from DB using the User object(obj)
return name
def get_size(self, obj):
# get size from DB using the User object(obj)
return size
I am trying to enable post methods in my borrowedview to enable admins, select from current users, and also select from the available books.
serializers.py
class BookListSerializer(serializers.ModelSerializer):
authors = serializers.SlugRelatedField(many = True, queryset = models.Author.objects.all(),slug_field = 'name',) #To represent the relationship as a string instead of id
genre = serializers.SlugRelatedField(many = True,queryset = models.Genre.objects.all(),slug_field = 'name')
class Meta:
model = models.Book
fields = ('name','authors','rating', 'genre')
class BorrowedSerializer(serializers.ModelSerializer):
who_borrowed = serializers.PrimaryKeyRelatedField(queryset = get_user_model().objects.all() ,source = 'who_borrowed.username',)
name = serializers.PrimaryKeyRelatedField(queryset = models.Book.objects.all(),
source = 'name.name',)
#borrowed_date = serializers.DateTimeField(format = "%H:%M, %d-%m-%Y")
#returned_date = serializers.DateTimeField(format = "%H:%M, %d-%m-%Y" )
class Meta:
model = models.Borrowed
fields = ('who_borrowed','name','has_returned','borrowed_date','returned_date',)
Then my models
models.py
class Book(models.Model):
name = models.CharField(max_length = 150,) #Name of books
authors = models.ManyToManyField(Author,)
genre = models.ManyToManyField(Genre)
publisher = models.ForeignKey(Publisher, on_delete = models.SET_DEFAULT, default = '2')
#A book should have a publisher will include a none field for books without publishers
pub_date = models.DateField()
price = models.DecimalField(max_digits = 10, decimal_places = 2)
isbn = models.CharField(max_length = 13, unique = True, null = True, blank = True,
validators = [MinLengthValidator(13)])
class Borrowed(models.Model): #Model for users borrowing and returning
name = models.ForeignKey(Book, on_delete = models.CASCADE,) #Consider making one to many field
borrowed_date = models.DateTimeField(auto_now_add = True, ) #Date is created as soon as instance is created
has_returned = models.BooleanField(default = False) #Field that determines if a model is returend or not
returned_date = models.DateTimeField(null = True, blank = True,) #Date that changes as soon as book is returned
who_borrowed = models.ForeignKey(get_user_model(), on_delete = models.SET_DEFAULT, default ='9c495b90-3900-43d1-875d-6b15d5d5ab55')
The Django browseable api shows the books to choose from and the user borrowing the book just as I want but when I want to post the request it shows the error from the title.
I don't know how to make a create method that would allow those options to show and would allow the post or put requests.
In a nutshell if I remove the source argument everything works fine, but I want the data shown not to be the Id or the UUID but the usernames and the names of the books instead.
You can refer DRF- doc.
Following changes should be enough in your case.
class BorrowedSerializer(serializers.ModelSerializer):
who_borrowed = serializers.PrimaryKeyRelatedField(queryset = get_user_model().objects.all() ,source = 'who_borrowed.username',)
name = serializers.PrimaryKeyRelatedField(queryset = models.Book.objects.all(),
source = 'name.name',)
class Meta:
model = models.Borrowed
fields = ('who_borrowed','name','has_returned','borrowed_date','returned_date',)
def create(self, validated_data):
return models.Borrowed.objects.create(**validated_data)
# or
# return super(BorrowedSerializer, self).create(validated_data)
class BorrowedSerializer(serializers.ModelSerializer):
who_borrowed = serializers.SlugRelatedField(queryset = get_user_model().objects.all(),slug_field = 'username')
name = serializers.SlugRelatedField(queryset = models.Book.objects.all(), slug_field = 'name')
Changing the "PrimaryKeyRelatedFields" to "SlugRelatedFields" also worked for me.
The message of the error the create method doesn't support writable dotted source fields by default is refering to name.name in the source argument of the customized serializer field,
so other ways to solve this are :
1. add a readonly=True in your new field
2. delete the customized field, so you get back to the id instead of the name.
I have two Models:
class MasterData(models.Model):
ID = models.AutoField(primary_key=True)
Companyname = models.CharField('Companyname', max_length=128, blank=True, null=True)
UserID = models.IntegerField('UserID')
class Prefixes(models.Model):
ID = models.AutoField(primary_key=True)
UserID = models.ForeignKey('MasterData', on_delete=models.CASCADE)
InvoiceNoPrefix = models.CharField('InvoiceNoPrefix', max_length=5, blank=True, null=True)
No I want in my view a make a simple objects.get_or_create if you visit the site the first time and no records exist should it create one.
#login_required(login_url='/backend/')
def edit_prefixes(request):
user_id = request.user.id
userfrommasterdata = MasterData.objects.filter(UserID__in=user_id)
prefixes_data = Prefixes.objects.get_or_create(UserID=userfrommasterdata)
And all what I get is a: 'int' object is not iterable
What do I miss? On my MasterData view it's working perfectlit:
#login_required(login_url='/backend/')
def edit_masterdata(request):
user_id = request.user.id
# stamdata_data = get_object_or_404(Stamdata, pk=user_id)
stamdata_data, _ = MasterData.objects.get_or_create(UserID__iexact=user_id, UserID=user_id)
filter() will always give you a QuerySet, even if only a single object matches the query - in this case, it will be a QuerySet containing a single element.
If you know there is only one object that matches your query, you can use the get() method which returns the object directly:
More Information from Django Documentation
try this:
userfrommasterdata = MasterData.objects.filter(UserID=user_id).first()
#login_required(login_url='/backend/')
def edit_prefixes(request):
user_id = request.user.id
userfrommasterdata = MasterData.objects.filter(UserID=user_id).first()
prefixes_data, _ = Prefixes.objects.get_or_create(UserID=userfrommasterdata)
I am Django rest framework to return the list of objects who do not have a foreign key in another table. what queryset should I write to get those objects.
models.py
class Event(models.Model):
id = models.IntegerField(primary_key=True)
title = models.CharField(max_length=100,default='')
description = models.TextField(blank=True,default='', max_length=1000)
link = models.URLField(null=True)
image = models.ImageField(null=True, blank=True)
organizer = models.CharField(max_length=100, default='')
timings = models.DateTimeField(default=None)
cost = models.IntegerField(default=1,null=True,blank=True)
def __str__(self):
return self.title
class Featured(models.Model):
event = models.ForeignKey(Event, null=True ,on_delete=models.PROTECT, related_name="event")
def __str__(self):
return self.event.title
class Meta:
verbose_name_plural = 'Featured'
views.py
class Upcoming2EventsViewSet(mixins.RetrieveModelMixin,mixins.ListModelMixin,viewsets.GenericViewSet):
serializer_class = Upcoming2Events
def get_queryset(self):
featured_events = Featured.objects.all().values_list('id')
return Event.objects.filter(id__in=featured_events)
# return Event.objects.exclude(id__in=featured_events.event.id)
# # return Event.objects.exclude(id__in = [featured_events.id])
serializers.py
class Upcoming2Events(serializers.ModelSerializer):
id = serializers.CharField(source='event.id')
title = serializers.CharField(source='event.title')
timings = serializers.DateTimeField(source='event.timings')
organizer = serializers.CharField(source='event.organizer')
class Meta:
model = Featured
fields = ['id','title','organizer','timings']
Error
Got AttributeError when attempting to get a value for field `id` on serializer `Upcoming2Events`.
The serializer field might be named incorrectly and not match any attribute or key on the `Event` instance.
Original exception text was: 'RelatedManager' object has no attribute 'id'.
Can you tell me what queryset should I write to get the only objects which are not present in the table Featured?
Also, what should I do to get only the upcoming 2 events from the Event table which are not present in the Featured table?
Note I am not supposed to use any flag value, can you provide some other solutions?
Based on the Informations you wrote here, i would suggest using a flag to determine a featured event. A second Model is useful if you want to provide more Informations on this specific for a featured event
like this:
class Event(models.Model):
id = models.IntegerField(primary_key=True)
title = models.CharField(max_length=100,default='')
description = models.TextField(blank=True,default='', max_length=1000)
link = models.URLField(null=True)
image = models.ImageField(null=True, blank=True)
organizer = models.CharField(max_length=100, default='')
timings = models.DateTimeField(default=None)
cost = models.IntegerField(default=1,null=True,blank=True)
featured = models.BooleanField(default=False)
so you can directly use querysets to get what you want:
Event.objects.exclude(featured=True)
Event.objects.exclude(featured=True).order_by('-timings')[:2]
I would use ModelViewsets directly, hence you will use your model here.
views and serializers would look like this:
views.py
class Upcoming2EventsViewSet(viewesets.ReadyOnlyModelViewSet):
serializer_class = EventSerializer
queryset = Event.objects.exclude(featured=True).order_by('-timings')[:2]
serializers.py
class EventSerializer(serializers.ModelSerilizer):
class Meta:
model = Event
fields = ['id', 'title', 'organizer', 'timings']
As improvement i would provide filters instead of setting up different ViewSets for just filtering querysets.
I have written a view that let me store some datas in a database:
def save(request, product_id):
product = Product.objects.get(pk=product_id)
user = request.user
p = SavedProduct(username= user, product_off_id=product.off_id)
p.save()
This is my models:
class Product(models.Model):
name = models.CharField(max_length=2000)
off_id = models.BigIntegerField()
class SavedProduct(models.Model):
username = models.CharField(max_length=2000)
product_off_id = models.BigIntegerField()
It does the job but I am struggling to implement a OneToOneField to username and product_off_id.
I know product_off_id = models.BigIntegerField() should be product_off_id =models.OneToOneField(Product) but what should I pass in p=SavedProduct() for the product_off_id field?
if you want to do it with the OneToOneField it would be:
p = SavedProduct(username= user, product_off_id=product)