When calling the update API i and getting this Error: 'QuerySet' object has no attribute '_meta'
Please have a look at my code, not sure where i am going wrong.
models.py
class FarmerAdvisory(models.Model):
'''
Farmer Advisory model definition
'''
CATEGORY_CHOICES = (
("CROP", "CROP"),
("WEATHER", "WEATHER"),
("FARMLAND", "FARMLAND")
)
SUB_CATEGORY_CHOICES = (
# ("CROP", "CROP"),
# ("WEATHER", "WEATHER"),
# ("FARMLAND", "FARMLAND")
)
STATUS_CHOICES = (
('OPEN', 'OPEN'),
('IN-PROGRESS', 'IN-PROGRESS'),
('CLOSED', 'CLOSED')
)
id = models.AutoField(db_column='id', primary_key=True)
category = models.CharField(db_column='category', max_length=100, null=False, blank=False, choices=CATEGORY_CHOICES)
sub_category = models.CharField(db_column='sub_category', max_length=100, null=False, blank=False)
# ,choices=SUB_CATEGORY_CHOICES)
title = models.CharField(db_column='title', max_length=200, null=True, blank=True)
description = models.CharField(db_column='description', max_length=500, null=True, blank=True)
media = models.JSONField(db_column='media', blank=True, null=True)
status = models.CharField(db_column='status', max_length=15, null=False, blank=False, default='OPEN',
choices=STATUS_CHOICES)
# assigned_to =
reply = models.CharField(db_column='reply', max_length=500, null=True, blank=True)
reply_media = models.JSONField(db_column='reply_media', blank=True, null=True)
label = models.CharField(db_column='label', max_length=100, null=True, blank=True)
farmer_id = models.ForeignKey(Farmer, on_delete=models.CASCADE, db_column='farmer_id')
objects = models.Manager()
class Meta:
managed = True
db_table = 'farmer_advisory'
serializers.py
class FarmerAdvisorySerializer(serializers.ModelSerializer):
class Meta:
model = FarmerAdvisory
fields = '__all__'
views.py
class FarmerAdvisoryObjectView(ShortCircuitMixin, APIView):
def put(self, request, farmer_id, adv_id):
try:
farmer_adv = FarmerAdvisory.objects.filter(farmer_id=farmer_id, id=adv_id)
serializer = FarmerAdvisorySerializer(farmer_adv, data=request.data)
if serializer.is_valid(raise_exception=True):
serializer.save()
response = JsonResponse(serializer.data, status=status.HTTP_201_CREATED)
return response
return Response(serializer.errors, status=status.HTTP_400_BAD_REQUEST)
except Exception as ex:
logger.error(traceback.format_exc())
return Response(data={"Error": str(ex)}, status=status.HTTP_500_INTERNAL_SERVER_ERROR)
`
urls.py
`
path('mobile/v1.1/farmer/<int:farmer_id>/farmer-adv/<int:adv_id>', FarmerAdvisoryObjectView.as_view(),
name='farmer_advisory_put')
I was expecting an update api to work and update the Model based on the path params.
I think you need to use get query instead of filter like this...
farmer_adv = FarmerAdvisory.objects.get(farmer_id=farmer_id, id=adv_id)
serializer = FarmerAdvisorySerializer(farmer_adv, data=request.data)
Related
I'm trying to use a many to many field in order to add a set of facilities to a lead.
The trouble is that i need an extra field for the date and time of the tour scheduled for each of the facilities i add to the lead.
So when i create a lead and add facilities to the lead i have that extra field where i can enter date and time and access it afterwards as a list of facilities with their tour dates on the leads page.
I came across many to many fields using "through" but I'm not sure if that's even the right option to use in this case. ManyToMany Fields with extra fields
How can i use a many to many field using "through" and have the through field automatically be generated for each facility i add to my lead with the many to many field? Or is using through not a good option?
I'm using Django Rest Framework with a React Frontend:
models.py
class Facility(models.Model):
Name = models.CharField(max_length=150, null=True, blank=False)
mainimage = models.ImageField(null=True, blank=True)
Email = models.EmailField(max_length=150, null=True, blank=True)
TelephoneNumber = models.CharField(max_length=30, null=True, blank=True)
FacilityDescription = models.TextField(max_length=1000, null=True, blank=True)
def __str__(self):
return self.Name
class Lead(models.Model):
assigned_facilities = models.ManyToManyField(Facility, related_name='assigned_facilities', null=True, blank=True)
first_name = models.CharField(max_length=40, null=True, blank=True)
last_name = models.CharField(max_length=40, null=True, blank=True)
def __str__(self):
return f"{self.first_name} {self.last_name}"
serializers.py
class LeadUpdateSerializer(serializers.ModelSerializer):
is_owner = serializers.SerializerMethodField()
class Meta:
model = Lead
fields = (
"id",
"first_name",
"last_name",
"assigned_facilities",
)
read_only_fields = ("id")
def get_is_owner(self, obj):
user = self.context["request"].user
return obj.agent == user
Leads.js
const cpBoard = useSelector((state) => state.cpBoard);
const facilityIds = (cpBoard.cpBoardItems?.map(cpBoardItem => (cpBoardItem.id)));
function submitFacilities() {
axios.patch(API.leads.update(id), { "assigned_facilities": facilityIds}, {
headers: {
"Authorization": `Bearer ${accessToken}`,
'Accept' : 'application/json',
},
withCredentials: true,
})
.then(res => {
fetchLeads()
})
.finally(() => {
})
}
UPDATE:
I'm currently trying to use the solution suggested below but i'm getting an error when i try to update a lead:
AttributeError: 'NoneType' object has no attribute 'scheduled_datetime' File "/serializers.py", line 253, in to_representation ret["scheduled_datetime"] = str(instance.leadfacilityassociation.first().scheduled_datetime)
models.py
class Facility(models.Model):
name = models.CharField(max_length=150, null=True, blank=False)
main_image = models.ImageField(null=True, blank=True)
email = models.EmailField(max_length=150, null=True, blank=True)
telephone_number = models.CharField(max_length=30, null=True, blank=True)
facility_description = models.TextField(max_length=1000, null=True, blank=True)
def __str__(self):
return self.Name
class Lead(models.Model):
first_name = models.CharField(max_length=40, null=True, blank=True)
last_name = models.CharField(max_length=40, null=True, blank=True)
def __str__(self):
return f"{self.first_name} {self.last_name}"
class LeadFacilityAssociation(models.Model):
assigned_facilities = models.ForeignKey(Facility, related_name='leadfacilityassociation')
lead = models.ForeignKey(Lead, related_name='leadfacilityassociation')
scheduled_datetime = models.DateTimeField(null=True, blank=True)
serializers.py
class LeadUpdateSerializer(serializers.ModelSerializer):
is_owner = serializers.SerializerMethodField()
assigned_facilities = serializers.Integer(required=True)
scheduled_datetime = serializers.DateTimeField(required=True)
class Meta:
model = Lead
fields = (
"id",
"first_name",
"last_name",
"assigned_facilities",
"scheduled_datetime",
)
read_only_fields = ("id")
def get_is_owner(self, obj):
user = self.context["request"].user
return obj.agent == user
def create(self, validated_data):
assigned_facilities = validated_data.pop("assigned_facilities")
scheduled_datetime = validated_data.pop("scheduled_datetime")
instance = Lead.objects.create(**validated_data)
instance.leadfacilityassociation.create(assigned_facilities=assigned_facilities,scheduled_datetime=scheduled_datetime)
return instance
def to_representation(self, instance):
ret = super().to_representation(instance)
ret["scheduled_datetime"] = str(instance.leadfacilityassociation.first().scheduled_datetime)
ret["assigned_facilities"] = instance.leadfacilityassociation.first().assigned_facilities
return ret
ManyToManyField is basically create another association model on Database level to associate ModelA(id) with ModelB(id). We are unable to add additional fields in it.
Now in your case, let's restructure the schema.
class Facility(models.Model):
name = models.CharField(max_length=150, null=True, blank=False)
main_image = models.ImageField(null=True, blank=True)
email = models.EmailField(max_length=150, null=True, blank=True)
telephone_number = models.CharField(max_length=30, null=True, blank=True)
facility_description = models.TextField(max_length=1000, null=True, blank=True)
def __str__(self):
return self.Name
class Lead(models.Model):
first_name = models.CharField(max_length=40, null=True, blank=True)
last_name = models.CharField(max_length=40, null=True, blank=True)
def __str__(self):
return f"{self.first_name} {self.last_name}"
class LeadFacilityAssociation(models.Model):
assigned_facilities = models.ForeignKey(Facility, related_name='leadfacilityassociation')
lead = models.ForeignKey(Lead, related_name='leadfacilityassociation')
scheduled_datetime = models.DateTimeField(null=True, blank=True)
Class Facility: The fields remains same in this Model.
Class Model: Remove assigned_facilities field from because we no longer need it.
Class LeadFacilityAssociation: Adding this Model to associate the Lead and Facility with additional scheduled_datetime field. Now you are able to mapped multiple Leads with multiple Facility with separate scheduled_datetime.
Serializer
class LeadUpdateSerializer(serializers.ModelSerializer):
is_owner = serializers.SerializerMethodField()
assigned_facilities = serializers.Integer(required=True)
scheduled_datetime = serializers.DateTimeField(required=True)
class Meta:
model = Lead
fields = (
"id",
"first_name",
"last_name",
"assigned_facilities",
"scheduled_datetime",
)
read_only_fields = ("id")
def get_is_owner(self, obj):
user = self.context["request"].user
return obj.agent == user
def create(self, validated_data):
assigned_facilities = validated_data.pop("assigned_facilities")
scheduled_datetime = validated_data.pop("scheduled_datetime")
instance = Lead.objects.create(**validated_data)
instance.leadfacilityassociation.create(assigned_facilities=assigned_facilities,scheduled_datetime=scheduled_datetime)
return instance
def to_representation(self, instance):
ret = super().to_representation(instance)
ret["scheduled_datetime"] = str(instance.leadfacilityassociation.first().scheduled_datetime)
ret["assigned_facilities"] = instance.leadfacilityassociation.first().assigned_facilities
return ret
Note
This serializer is designed to create only one Lead with one Facility. For creating multiple facilities you can change the overrided method create. Use bulk_create for creating multiple facilities against Lead. Also change the to_representation method body for returning multiple facilities against Lead.
Using through= seems the way to go in your case. To achieve it you need to create a Model for your M2M table
LeadFacility(models.Model):
facility = models.ForeignKey(Facility, on_delete=models.CASCADE)
lead = models.ForeignKey(Lead, on_delete=models.CASCADE)
datetime = models.DateTimeField()
You can set the datetime value using the following syntax :
my_lead.assigned_facilities.add(my_facility, through_defautlts={"datetime": my_datetime})
Or simply creating the LeadFacilty explicitly :
LeadFacility.objects.create(lead=my_lead, facility=my_facility, datetime=my_datetime)
To access those fields, you'll to define related_names in the LeadFacility model
I am getting Issue while edit a record based on CHatquestion ID, if option is null then i need to add a record based on same chatquestion id, if chatqustion id exist in option it will work,
i am trying to multiple way to solve this issue but still can't find solution.
Models.py # thease are all 3 models
class Problem(models.Model):
Language = models.IntegerField(choices=Language_CHOICE, default=1)
type = models.CharField(max_length=500, null=True, blank=True)
def __str__(self):
return self.type
class ChatQuestion(models.Model): # Eding record based on chatquestion id
question = RichTextField(null=True, blank=True)
problem_id = models.ForeignKey(
Problem,
models.CASCADE,
verbose_name='Problem',
)
def __str__(self):
return self.question
is_first_question = models.BooleanField(default=False)
class Option(models.Model):
option_type = models.CharField(max_length=250, null=True, blank=True)
question_id = models.ForeignKey(
ChatQuestion,
models.CASCADE,
verbose_name='Question',
null=True,
blank=True
)
problem=models.ForeignKey(
Problem,
models.CASCADE,
verbose_name='Problem',
null=True,
blank=True
)
next_question_id = models.ForeignKey(ChatQuestion, on_delete=models.CASCADE, null=True, blank=True,
related_name='next_question')
def __str__(self):
return self.option_type
forms.py
class EditQuestionForm(forms.ModelForm):
class Meta:
model = ChatQuestion
fields =('question','problem_id')
class EditOptionForm(forms.ModelForm):
class Meta:
model = Option
fields =('option_type',)
views.py
def question_edit(request,id=None):
if id is not None:
queryset = get_object_or_404(ChatQuestion,pk=id)
queryset1=get_object_or_404(Option,question_id=queryset )
else:
queryset = None
queryset1 = None
if request.method=="POST":
form = EditQuestionForm(request.POST ,instance=queryset)
form1=EditOptionForm(request.POST, instance=queryset1)
if form.is_valid() and form1.is_valid():
question=form.cleaned_data['question']
option_type=form1.cleaned_data['option_type']
if id:
queryset.question=question
queryset.save()
queryset1.option_type=option_type
queryset1.save()
messages.success(request,'Sucessful')
return redirect('/fleet/list_chatbot')
else:
print(form.errors)
messages.error(request,'Please correct following',form.errors)
elif id:
form = EditQuestionForm(instance=queryset)
form1=EditOptionForm(instance=queryset1)
if not queryset1:
form1=EditOptionForm()
else:
form = EditQuestionForm()
form1=EditOptionForm()
context={
'form':form,
'form1':form1
}
return render(request,'chatbot/question_edit.html',context=context)
I'm creaating an api that user can create a job. when I want to test it with postman and create a job I have this error:
IntegrityError at /job/create/
NOT NULL constraint failed: core_job.category_id
how do i can fix it ?? I'm using generic CreateAPIView
models:
class Category(models.Model):
name = models.CharField(max_length=300)
slug = models.SlugField(max_length=300, unique=True, help_text='write in English.')
sub_category = models.ForeignKey('Category', null=True, blank=True, on_delete=models.CASCADE)
class Job(models.Model):
user = models.OneToOneField(settings.AUTH_USER_MODEL, on_delete=models.CASCADE)
name = models.CharField(max_length=400, unique=True)
slug = models.SlugField(max_length=400, unique=True, allow_unicode=True)
category = models.ForeignKey(Category, on_delete=models.DO_NOTHING)
image_1 = models.ImageField(upload_to='products_pic/%Y/%m/%d/', null=True, blank=True)
description = models.TextField(null=True, blank=True)
phone1 = models.CharField(max_length=12, null=True, blank=True)
phone2 = models.CharField(max_length=12, null=True, blank=True)
phase = models.CharField(max_length=1, null=True, blank=True)
address = models.TextField(null=True, blank=True)
daily_start_work_time = models.TimeField(null=True, blank=True)
daily_end_work_time = models.TimeField(null=True, blank=True)
create_date = models.DateTimeField(auto_now_add=True)
update_date = models.DateTimeField(auto_now=True)
active = models.BooleanField(default=False)
popular = models.BooleanField(default=False)
views:
class JobCreateView(generics.CreateAPIView):
permission_classes = (IsAuthenticated,)
serializer_class = JobSerializer
queryset = Job.objects.all()
serializers:
class CategorySerializer(serializers.ModelSerializer):
class Meta:
model = Category
fields = '__all__'
class JobSerializer(serializers.ModelSerializer):
category = serializers.SerializerMethodField()
class Meta:
model = Job
fields = '__all__'
lookup_field = 'slug'
extra_kwargs = {
'url': {'lookup_field': 'slug'}
}
def get_category(self, obj):
return obj.category.name
The category field is not populating with any value when you create the job. I mean category field is Null when you save that form. I am not sure but any way the problem is related to category field
so I am building a pet blog project where my scenario is - my users will be able to post multiple images and audios if they want while doing so , am facing several problems -
while trying to post through POSTMAN . I am getting an error saying create() got multiple values for keyword argument 'hnid' ..
while querying using UUID , it is throwing , a String naming "HNUsers object (e3ec1a43-ebc4-47b9-bf2f-55967af8ea71)" where I just wanted UUID(e3ec1a43-ebc4-47b9-bf2f-55967af8ea71) but came with extra HNUsers object
Here is my Profile model
class HNUsers(models.Model):
USERTYPE = (
(u'RU', u'REGULAR USER'),
(u'HN', u'HN'),
)
GENDER = (
(u'M', u'Male'),
(u'F', u'Female'),
(u'O', u'Other'),
)
ip_address = models.CharField("IP Address" , max_length=100, blank=True, null=True)
full_name = models.CharField("Full Name", max_length=100, null=True, blank=True)
username = models.CharField("Username", max_length=100, null=True, blank=True)
email = models.EmailField("Email", blank=True, null=True)
user_type = models.CharField("User Type", max_length=2, choices=USERTYPE, null=True, blank=True, default=USERTYPE[0][0])
mobile_number = models.CharField("Mobile Number", max_length=20, blank=True, null=True)
date_of_birth = models.DateField("Date of Birth", auto_now_add=False, blank=False, null=True)
gender = models.CharField("Gender", max_length=1, choices=GENDER, blank=True, null=True, )
registration_date = models.DateTimeField("Registration Date", auto_now_add=True, null=True, blank=True)
city = models.CharField("City", max_length=50, blank=True, null=True)
country = models.CharField("Country", max_length=50, blank=True, null=True)
profile_img = models.ImageField("Profile Image", blank=True, null=True)
first_img = models.FileField("First Image", blank=True, null=True)
first_img_url = models.CharField("First Image Url", blank=True, null=True, max_length=500)
profile_img_url = models.CharField("Profile Image Url", blank=True, null=True, max_length=500)
hnid = models.UUIDField("HNID", default=uuid.uuid4, unique=True, primary_key=True, editable=False)
my imagepost model
class ImagePost(models.Model):
hnid = models.ForeignKey("profiles.HNUsers", on_delete=models.DO_NOTHING)
file = models.FileField("Image", blank=True, null=True)
timestamp = models.DateTimeField("Timestamp", blank=True, null=True, auto_now_add=True)
text = models.TextField("Description text", blank=True)
class Meta:
verbose_name_plural = "Image Posts"
serializer for image post
class MultiMediaSerializer(serializers.ModelSerializer):
file = serializers.ListField(child=serializers.FileField(max_length=100, allow_empty_file=False, use_url=True))
def create(self, validated_data):
request = self.context.get('request')
# print(validated_data)
files = validated_data.pop('file')
print(files)
user = HNUsers.objects.get(pk=request.data['hnid'])
print("hnid ", user)
# print("hnid ", entry)
for img in files:
print(img)
photo = ImagePost.objects.create(file=img, hnid=user, **validated_data)
return photo
class Meta:
model = ImagePost
fields = ('hnid', 'file',)
Views.py file for the above is -
#api_view(['POST'])
#permission_classes((permissions.AllowAny,))
#parser_classes([MultiPartParser, FormParser])
def posting_api(request):
if request.method == 'POST':
data = request.data
print(data)
serializer = MultiMediaSerializer(data=data, context={'request': request})
if serializer.is_valid():
serializer.save()
print("image object saved")
return Response(serializer.data, status=status.HTTP_201_CREATED)
Sorry I am new to this
Remove hnid=user from the create statement since the validated_data does have the hnid field already
photo = ImagePost.objects.create(file=img, **validated_data)
I am using django rest framework wherein the model has composite primary key, one of the them being a foreign key.
models/TestSuite.py
class TestSuite(models.Model):
team_name = models.ForeignKey('Team', on_delete=models.DO_NOTHING, db_column='team_name')
suite_name = models.CharField(max_length=100)
description = models.CharField(max_length=200, blank=True, null=True)
schedule = models.CharField(max_length=100, blank=True, null=True)
email_list_ok = models.CharField(max_length=200, blank=True, null=True)
email_list_fail = models.CharField(max_length=200, blank=True, null=True)
template_name = models.ForeignKey('EmailTemplates', on_delete=models.DO_NOTHING, db_column='template_name')
class Meta:
managed = False
db_table = 'test_suite'
unique_together = (('team_name', 'suite_name'),)
models/Team.py
class Team(models.Model):
team_name = models.CharField(primary_key=True, max_length=30)
description = models.CharField(max_length=100, blank=True, null=True)
class Meta:
managed = False
db_table = 'team'
TestSuiteSerializer.py
class Meta:
model = models.TestSuite
fields = '__all__'
TestSuiteViewSet.py
class TestSuiteViewSet(viewsets.ModelViewSet):
queryset = models.TestSuite.objects.all()
serializer_class = serializers.TestSuiteSerializer
def create(self, request, *args, **kwargs):
serializer = self.get_serializer(data=request.data,
many=isinstance(request.data, list))
serializer.is_valid(raise_exception=True)
self.perform_create(serializer)
headers = self.get_success_headers(serializer.data)
return Response(serializer.data,
status=status.HTTP_201_CREATED, headers=headers)
Now when I do a post request, it throws below errors
When the post() has team_name already existing in team table
{
"team_name": [
"test suite with this team name already exists."
]
}
When the post() has team_name not existing in team table
Exception Type: ValueError
Exception Value:
Cannot assign "'dummy'": "TestSuite.team_name" must be a "Team" instance.
Can someone please help me here. I am assuming I am missing something.
The first argument to your foreign key fields should be the model itself, not a string of the model (eg. not 'Team', but Team - likewise for EmailTemplate)
class TestSuite(models.Model):
# Change this field's first argument from a string to the Team class
team_name = models.ForeignKey(Team, on_delete=models.DO_NOTHING, db_column='team_name')
suite_name = models.CharField(max_length=100)
description = models.CharField(max_length=200, blank=True, null=True)
schedule = models.CharField(max_length=100, blank=True, null=True)
email_list_ok = models.CharField(max_length=200, blank=True, null=True)
email_list_fail = models.CharField(max_length=200, blank=True, null=True)
# Change this field's first argument from a string to the EmailTemplates class
template_name = models.ForeignKey(EmailTemplates, on_delete=models.DO_NOTHING, db_column='template_name')
class Meta:
managed = False
db_table = 'test_suite'
unique_together = (('team_name', 'suite_name'),)