Django a simple query makes me crazy ''int' object is not iterable' - django

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)

Related

Django Rest Framework Serializer PrimaryKeyRelatedField pass in uuid list

So, I am trying to make a social media application and users can tag other users in their post.
class Post(models.Model):
author = models.ForeignKey(User, related_name='posts', on_delete=models.CASCADE)
caption = models.CharField(max_length=100, null=True, blank=True)
id = models.UUIDField(default=uuid.uuid4, unique=True, primary_key=True, editable=False)
date_created = models.DateTimeField(auto_now_add=True)
date_edited = models.DateTimeField(auto_now=True)
allow_comments = models.BooleanField(default=True)
archived = models.BooleanField(default=False)
media_file_url = models.FileField(upload_to='videos/', validators=[validate_file_extension])
tags = TaggableManager(blank=True, through=TaggedHashtag)
mentioned_users = models.ManyToManyField(User, blank=True, through='MentionedUser')
class MentionedUser(models.Model):
id = models.UUIDField(default=uuid.uuid4, unique=True, primary_key=True, editable=False)
date_created = models.DateTimeField(auto_now_add=True)
post = models.ForeignKey(Post, on_delete=models.CASCADE)
tagged_user = models.ForeignKey(User, on_delete=models.CASCADE)
class Meta:
unique_together = (('post', 'tagged_user'))
ordering = ['date_created']
For serializing the uuids for the mentioned_users, I followed these instructions. Everything works fine, I can submit one uuid correctly like this:
But when I try to submit more than one uuids, I get this error:
Here is my serializer:
class PostSerializer(TaggitSerializer, serializers.ModelSerializer):
tags = TagListSerializerField()
mentioned_users = serializers.PrimaryKeyRelatedField(many=True, allow_null=True, queryset=User.objects.all(), pk_field=serializers.UUIDField(format='hex'))
id = serializers.CharField(read_only=True)
class Meta:
model = Post
fields = [
'caption',
'allow_comments',
'media_file_url',
'id',
'tags',
'mentioned_users',
]
What am I doing wrong here? What is the correct way to submit list of uuids? Also, is the present method I am using efficient, any form of help would be appreciated. Thank You.
Also, I tried adding double quotes for the uuids and also, tried to use '[]' box brackets, but it did not solve my problem.
PS - When I post data to this API from a mobile app, how will I submit it, will it be the same way here or will it be different?
After trying to use ListField(), a drf serializer, and it having its own cannot be empty list error, I took inspiration from TagListSerializer() from django-taggit, and made my own custom serializer, I can upload strings, even empty list, which basically means I don't want to tag anyone. However, I do have to check if the string is valid uuid.
Here is the code for the serializer
from rest_framework import serializer
import json
from django.utils.translation import gettext_lazy
class MentionedUsersIdSerializerField(serializers.Field):
child = serializers.CharField()
initial = []
default_error_messages = {
"not_a_list": gettext_lazy(
'Expected a list of items but got type "{input_type}".'
),
"invalid_json": gettext_lazy(
"Invalid json list. A tag list submitted in string"
" form must be valid json."
),
"not_a_str": gettext_lazy("All list items must be of string type."),
}
order_by = None
def __init__(self, **kwargs):
pretty_print = kwargs.pop("pretty_print", True)
style = kwargs.pop("style", {})
kwargs["style"] = {"base_template": "textarea.html"}
kwargs["style"].update(style)
super().__init__(**kwargs)
self.pretty_print = pretty_print
def to_internal_value(self, value):
if isinstance(value, str):
if not value:
value = "[]"
try:
value = json.loads(value)
except ValueError:
self.fail("invalid_json")
if not isinstance(value, list):
self.fail("not_a_list", input_type=type(value).__name__)
for s in value:
if not isinstance(s, str):
self.fail("not_a_str")
self.child.run_validation(s)
return value
def to_representation(self, value):
if not isinstance(value, list):
if not isinstance(value, list):
if self.order_by:
ids = value.all().order_by(*self.order_by)
else:
ids = value.all()
value = [id.id for id in ids]
value = list(value, pretty_print=self.pretty_print)
return value
I hope this helps someone trying to submit a list of strings to the serializer, where the list can be empty as well.

Django advanced query - objects of a Foriegnkey?

I have a Django models where I have this :
class Patient(models.Model):
FirstName = models.CharField(max_length=264)
LastName = models.CharField(max_length=264)
Address = models.TextField(blank=True)
Telephone_no = models.CharField(max_length=100,blank=True)
user = models.ForeignKey(settings.AUTH_USER_MODEL,on_delete=models.CASCADE,related_name='patients')
class UploadedImages(models.Model):
patient = models.ForeignKey(Patient,on_delete=models.CASCADE,related_name='images')
original = models.ImageField(upload_to = user_directory_path, validators=[validate_file_extension],verbose_name = 'Image')
enhanced = models.ImageField(upload_to=analyses_directory_path, blank=True)
segmented = models.ImageField(upload_to=analyses_directory_path, blank=True)
class Processed(models.Model):
uploaded_image = models.ForeignKey(UploadedImages,on_delete=models.CASCADE,related_name='processed')
pre_analysed = models.ImageField(upload_to=analyses_directory_path, blank=True)
analysedimage = models.ImageField(upload_to=analyses_directory_path, blank=True)
so I want to make queries based on the current user which is user = request.user this is possible in the patient model case as I can make Patient.objects.filter(user=user)
but i can't make it the other 2 models
is there any idea how I can do this?
I didn't add the user FK as I thought I wouldn't need it but now I do?
do i need to add it ? can I make a query without adding the field ?
If you want to query across relationships, Django has explicit syntax for that. For example, to get all the UploadedImage objects for a specific user, use UploadedImage.objects.filter(patient__user=user).
Patient.objects.filter(user=user) returns a queryset, to get patient by user, assuming one Patient has only one user:
patient = Patient.objects.filter(user=user).first()
then you can do:
uploaded_images = patients.images.all()
for image in uploaded_images:
processed = image.processed.all()

django how to get model field as object

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)

Django: Field missing when queried

I'm having some trouble querying for my CalculatedAmt field in my database. In fact, according to the error code, the field does not even exist. However, I have included it in my Models.py and it can even be seen in my admin interface on Django.
Here are my codes:
Model.py - I didn't join the tables because I didn't need the join for my queries
class Customer(models.Model):
Customer_Name_P = models.CharField(max_length=30, default="missing")
Customer_TelNo = models.CharField(max_length=8, default="missing")
Postal_Code = models.CharField(max_length=6, default="missing")
def __str__(self):
return "%s" % self.Customer_Name_P
class Transaction(models.Model):
DocRef = models.CharField(max_length=10,default="missing")
DocDate = models.DateField()
AcCrIsMinus1 = models.CharField(max_length=10,default="missing")
AcCurWTaxAmt = models.CharField(max_length=10,default="missing")
HomeWTaxAmt = models.CharField(max_length=10,default="missing")
CalculatedAmt = models.CharField(max_length=10, default="missing")
ProjectCode = models.CharField(max_length=10,default="missing")
Location = models.CharField(max_length=10,default="missing")
Sales_Person = models.CharField(max_length=10,default="missing")
AcCode = models.CharField(max_length=8,default="missing")
Customer_Name = models.CharField(max_length=30,default="missing")
def __str__(self):
return "%s" % self.id
class Salesperson(models.Model):
Sales_Person_P = models.CharField(max_length=10,default="missing",primary_key=True)
Sales_Person_Name = models.CharField(max_length=10,default="missing")
Sales_Person_Contact = models.CharField(max_length=10,default="missing")
def __str__(self):
return "%s" % self.Sales_Person_P
class Account(models.Model):
AcCode_P = models.CharField(max_length=8, default="missing",primary_key=True)
Customer_Name = models.CharField(max_length=30,default="missing")
AcCur = models.CharField(max_length=3, default="missing")
def __str__(self):
return "%s" % self.AcCode_P
Query in shell (for a table):
Transaction.objects.all().filter(Sales_Person=Sales_Person).values('DocRef','DocDate','AcCrIsMinus1','HomeWTaxAmt','ProjectCode','Customer_Name','Location')
Error Message:
django.core.exceptions.FieldError: Cannot resolve keyword 'CalculatedAmt' into field. Choices are: AcCode, AcCrIsMinus1, AcCurWTaxAmt, Customer_Name, DocDate, DocRef, HomeWTaxAmt, Location, ProjectCode, Sales_Person, id
Here's a screenshot of a Transaction instance from the admin interface:
screenshot
Screenshot of the output for python manage.py showmigrations:
screenshot
Screenshot of migrations 0001_initial file
screenshot
Thank you!
This error does not say that the field is missing. The FieldError exception is raised when there is a problem with a model field. This can happen for several reasons:
A field in a model clashes with a field of the same name from an
abstract base class
An infinite loop is caused by ordering
A keyword cannot be parsed from the filter parameters
A field cannot be determined from a keyword in the query parameters
A join is not permitted on the specified field
A field name is invalid A query contains invalid order_by arguments
Just for your information, for a field which does not exist there is a FieldDoesNotExist exception. It is raised by a model’s _meta.get_field() method when the requested field does not exist on the model or on the model’s parents.
The error is because you are fetching all() first then try to filter. When you fetch all you get all fields and then not include CalculatedAmt in your values.
t = Transaction.objects.filter(Sales_Person__iexact=Sales_Person)
t object will be containing all the field of Transaction so no need for .values, you can retrieve them by t.CalculatedAmt for example. P.s. ixact means exact matching without caring for case-sensitiveness.
Moreover, I assume you have tried to connect 2 models together with Sales_Person field. But you are doing it in the wrong way.
You should use one of the OnetoOne, ForeignKey or ManytoMany relationships. I will use ForeignKey assuming that a salesperson can have many transactions but each transaction can only belong to one person.
class Transaction(models.Model):
DocRef = models.CharField(max_length=10,default="missing")
DocDate = models.DateField()
AcCrIsMinus1 = models.CharField(max_length=10,default="missing")
AcCurWTaxAmt = models.CharField(max_length=10,default="missing")
HomeWTaxAmt = models.CharField(max_length=10,default="missing")
CalculatedAmt = models.CharField(max_length=10, default="missing")
ProjectCode = models.CharField(max_length=10,default="missing")
Location = models.CharField(max_length=10,default="missing")
Sales_Person = models.ForeignKey('Salesperson', on_delete=models.CASCADE)
AcCode = models.CharField(max_length=8,default="missing")
Customer_Name = models.CharField(max_length=30,default="missing")
def __str__(self):
return "%s" % self.id
class Salesperson(models.Model):
Sales_Person_P = models.CharField(max_length=10,default="missing",primary_key=True)
Sales_Person_Name = models.CharField(max_length=10,default="missing")
Sales_Person_Contact = models.CharField(max_length=10,default="missing")
def __str__(self):
return "%s" % self.Sales_Person_P

In Django REST framework, how do you access a field in a table referenced by a foreign key

I have the following models in Django:
class campaign(models.Model):
start_date = models.DateField('Start Date')
end_date = models.DateField('End Date')
description = models.CharField(max_length=500)
name = models.CharField(max_length=200)
active_start_time = models.TimeField()
active_end_time = models.TimeField()
last_updated = models.DateTimeField('Date updated',auto_now=True)
active = models.BooleanField(default=True)
client_id = models.ForeignKey('client',on_delete=models.PROTECT)
def __unicode__(self):
return u'%d | %s | %s' % (self.id,self.name, self.description)
class campaign_product(models.Model):
product_id = models.ForeignKey('product',on_delete=models.PROTECT)
last_updated = models.DateTimeField('Date updated',auto_now=True)
campaign_id = models.ForeignKey('campaign',on_delete=models.PROTECT)
class product(models.Model):
name = models.CharField(max_length=200)
description = models.CharField(max_length=500)
sku = models.CharField(max_length=200,blank=True,null=True)
retail_price = models.DecimalField(decimal_places=2,max_digits=11)
discount_price = ((1,'Yes'),(0,'No'))
discounted_price = models.DecimalField(decimal_places=2,max_digits=11,blank=True,null=True)
category_id = models.ForeignKey('category',on_delete=models.PROTECT)
last_updated = models.DateTimeField('Date updated',auto_now=True)
active = models.BooleanField(default=True)
def __unicode__(self):
return u'%d | %s' % (self.id, self.name)
I also have the following serializer:
class campaignProductSerializer(serializers.HyperlinkedModelSerializer):
class Meta:
model = campaign_product
fields = ('product_id', 'campaign_id')
And the following view set behavior in the urls.py file:
class campaignProductViewSet(viewsets.ModelViewSet):
queryset = campaign_product.objects.filter(campaign_id__start_date__lte=datetime.now(),campaign_id__end_date__gte=datetime.now(),campaign_id__active__exact=True)
serializer_class = campaignProductSerializer
My problem is I need to include the name field from the products model in my query results when for instance a request is made on http://127.0.0.1:8000/campaign_product/1/. Currenly this request returns only the product_id and the campaign_id. I tried making the serializer as follows:
class campaignProductSerializer(serializers.HyperlinkedModelSerializer):
class Meta:
model = campaign_product
fields = ('product_id', 'campaign_id', 'product.name')
But then the service returns the following error:
Field name `product.name` is not valid for model `campaign_product`.
I event tried using product__name with and without quotes. Without quotes it tells me that there is no such variable, and with quotes it gives the is not valid for model error similar to the above. Heeelp! Getting this extra field is proving to be a pain :-(
What you want will need to look something more like this:
class campaignProductSerializer(serializers.HyperlinkedModelSerializer):
product_name = serializers.CharField(source='product_id.name')
class Meta:
model = campaign_product
fields = ('product_id', 'campaign_id', 'product_name')
P.S. As an unrelated side note, it is generally a convention in Python code to name classes with CamelCase, such as Campaign, CampaignProduct, Product, and CampaignProductSerializer.
Edit: P.P.S. Originally, I had put written the product_name field with source='product.name'. This was actually due to me looking at the code too quickly and making assumptions based on Django conventions. Typically, with a Django ForeignKey, you would name the ForeignKey field after the model you are linking to, rather than explicitly naming it with _id. For example, the CampaignProduct model would typically be written with product = ForeignKey(...) and campaign = ForeignKey(...). In the background, Django will actually use product_id and campaign_id as the database field names. You also have access to those names on your model instances. But the product and campaign variables on your model instances actually return the objects which you are referring to. Hopefully that all makes sense.