error: 'Questions' object is not iterable
models.py code:
class Questions(models.Model):
title = models.CharField(max_length = 150)
slug = models.SlugField(max_length = 10, unique = True)
body = models.TextField()
category = models.ManyToManyField(Category, related_name = "questions")
author = models.ForeignKey(User, on_delete = models.CASCADE)
created = models.DateTimeField(auto_now_add = True)
picture = models.ImageField(upload_to = "questions/%Y/%m/%d", null = True, blank = True)
status = models.BooleanField(default = True)
def get_absolute_url(self):
return reverse("questions:ques_detail", args = [self.slug, self.id])
views.py code:
def QuestionDetail(request, question, pk):
question = get_object_or_404(Questions, slug = question, id = pk)
return render(request, "questions/ques_detail.html", {"questions": question})
urls.py code:
urlpatterns = [
path('<slug:question>/<int:pk>', QuestionDetail, name = "questiondetail")
I guess there is a misunderstanding somewhere.
Indeed what do you want to achieve ?
If you want to retrieve a single instance your code looks good but it does not make any sense to iterate on an instance.
If you want to retrieve a QuerySet, then you would have to create another view. For exemple :
def questions(request):
questions = get_list_or_404(Questions)
return render(request, "questions/ques_detail.html", {"questions": questions})
Also you should take care of naming your function and variable in a pythonic way.
Some docs might be found here
Related
I have the following codes:
models.py
class Job(models.Model):
jobname = models.CharField(max_length = 1000)
owner = models.CharField(max_length = 150)
enabled = models.BooleanField()
freq_type = models.IntegerField(default = 1)
freq_interval = models.IntegerField(default = 0)
freq_recurrence = models.IntegerField(default = 0)
start_date=models.CharField(max_length=10)
end_date=models.CharField(max_length=10, blank = True)
start_time=models.CharField(max_length=6)
end_time=models.CharField(max_length=6, blank = True)
date_added = models.DateTimeField(auto_now_add = True, null = True)
date_modified=models.DateTimeField(auto_now = True, null = True)
version=models.IntegerField(default = 1)
class Job_removed(models.Model):
jobname = models.CharField(max_length = 1000)
owner = models.CharField(max_length = 150)
enabled = models.BooleanField(null = True)
freq_type = models.IntegerField(default = 1)
freq_interval = models.IntegerField(default = 0)
freq_recurrence = models.IntegerField(default = 0)
start_date=models.CharField(max_length=10)
end_date=models.CharField(max_length=10, blank = True)
start_time=models.CharField(max_length=6)
end_time=models.CharField(max_length=6, blank = True)
date_added = models.DateTimeField(null = True)
date_modified=models.DateTimeField(default=timezone.now)
version=models.IntegerField(null=True)
views.py
def job_delete(request,pk):
job=Job.objects.get(pk=pk)
jobdetail = Job_detail.objects.get(job=pk)
if request.method == "POST":
jobr = JobRemovedForm(request.POST)
if jobr.is_valid():
jobr.jobname = job.jobname
print(jobr.jobname)
jobr.owner = job.owner
print(jobr.owner)
jobr.enabled = job.enabled
print(jobr.enabled)
jobr.start_date = job.start_date
print(jobr.start_date)
jobr.start_time = job.start_time
print(jobr.start_time)
jobr.date_added = job.date_added
print(jobr.date_added)
jobr.version = job.version
print(jobr.version)
jobr.save()
return redirect('/job/', {'job':Job.objects.all})
else:
jobr = JobRemovedForm()
return render(request, 'interface/job_removed.html', {'job':job, 'jobdetail':jobdetail, 'jobr':jobr})
return render(request, 'interface/job_removed.html', {'job':job, 'jobdetail':jobdetail})
Output of my powershell for those print commands:
In the database (SQLite):
What I am trying to do is to copy from the entry from Job Table to Job_removed Table. I assign the new entry in Job_removed with the values in Job Table. It is printing correctly in my powershell but when I check my database, none of the value are entering. Why is this happening though? Can anyone explain to me and point me to the right direction to correct this? I know there are post about how to clone data to another table but it does not fit the task that I am required to do so I am not using those answers.
Update: model for Job_detail and form for JobRemovedForm
models.py
class Job_detail(models.Model):
job_type=models.IntegerField(default=1)
json = models.CharField(max_length = 1000)
job = models.ForeignKey(Job, on_delete=models.CASCADE)
forms.py
class JobRemovedForm(ModelForm):
class Meta:
model = Job_removed
fields = []
Update 2: views (I realize i didnt do commit=False) and form fields updated
views.py
def job_delete(request,pk):
job=Job.objects.get(pk=pk)
jobdetail = Job_detail.objects.get(job=pk)
if request.method == "POST":
jobr = JobRemovedForm(request.POST)
if jobr.is_valid():
jr = jobr.save(commit=False)
jr.jobname = job.jobname
print(jr.jobname)
jr.owner = job.owner
print(jr.owner)
jr.enabled = job.enabled
print(jr.enabled)
jr.start_date = job.start_date
print(jr.start_date)
jr.start_time = job.start_time
print(jr.start_time)
jr.date_added = job.date_added
print(jr.date_added)
jr.version = job.version
print(jr.version)
jr.save()
return redirect('/job/', {'job':Job.objects.all})
else:
print(jobr.errors)
jobr = JobRemovedForm()
return render(request, 'interface/job_removed.html', {'job':job, 'jobdetail':jobdetail, 'jobr':jobr})
return render(request, 'interface/job_removed.html', {'job':job, 'jobdetail':jobdetail})
forms.py
class JobRemovedForm(ModelForm):
class Meta:
model = Job_removed
fields = ['jobname', 'owner', 'enabled', 'start_date', 'start_time', 'date_added', 'version']
And now my powershell is showing jobr.errors of the following:
jobnameThis field is required.ownerThis field is required.start_dateThis field is required.start_timeThis field is required.date_addedThis field is required.versionThis field is required.
Actually you do not need Job_removed model because it is unuseful and not better design for a such case in general.so first remove that model and add a field called is_deleted to your job model which value should be True for deleted jobs and False for non deleted jobs.by default i make is_deleted is False so when you deleted it you can mark it as True
class Job(models.Model):
jobname = models.CharField(max_length = 1000)
owner = models.CharField(max_length = 150)
enabled = models.BooleanField()
freq_type = models.IntegerField(default = 1)
freq_interval = models.IntegerField(default = 0)
freq_recurrence = models.IntegerField(default = 0)
start_date=models.CharField(max_length=10)
end_date=models.CharField(max_length=10, blank = True)
start_time=models.CharField(max_length=6)
end_time=models.CharField(max_length=6, blank = True)
date_added = models.DateTimeField(auto_now_add = True, null = True)
date_modified=models.DateTimeField(auto_now = True, null = True)
version=models.IntegerField(default = 1)
is_delete = models.BooleanField(default=False) # new field
Delete your model remove Job_removed
2)run python manage.py makemigrations
3)run python manage.py migrate
now let us work on your views for deleting jobs.
from django.shortcuts import render,get_object_or_404,redirect
def job_delete(request,pk):
job= get_object_or_404(Job,pk=pk,is_deleted=False)
job.is_deleted = True # delete the job if it is not deleted
job.save()
return redirect('/job/')
Note:I use get_object_or_404 to raise page not found if there is no job related to the pk and i check that the job is not deleted.
now i do not know how is your other views but you should now make a little bit of change in querying jobs.if you want to query all jobs you should query jobs that is not deleted.by doing this
Job.objects.filter(is_deleted = False)
instead of
Job.objects.all()
and better approach should be to use post method for deleting jobs not get.but for now you can keep as it is.sorry for my english if you do not understand please ask me in the comments.
Update but if you want to do is it as you did.
then you do not need a form you can just copy the data from Job to Job_removed.and if you need a form you can make these fields read only.
let us do it without form
from django.shortcuts import render,get_object_or_404,redirect
def job_delete(request,pk):
job= get_object_or_404(Job,pk=pk)
jr = Job_removed()
jr.jobname = job.jobname
print(jr.jobname)
jr.owner = job.owner
print(jr.owner)
jr.enabled = job.enabled
print(jr.enabled)
jr.start_date = job.start_date
print(jr.start_date)
jr.start_time = job.start_time
print(jr.start_time)
jr.date_added = job.date_added
print(jr.date_added)
jr.version = job.version
print(jr.version)
jr.save()
job.delete() # then delete the job
return redirect('/job/')
Form is not required in this situation.
Soft delete is the best option. Have a look in to this tutorial
I am not sure why the assertion below is failing.
Can someone please give me a feedback, I am new to pytest with django.
test.forms
#pytest.fixture
def product():
month = Month.objects.create(name="november", slug="november")
user = User.objects.create(username="james", password="password")
obj = Product.objects.create(
user=user,
name="broom",
price=19.99,
quantity=1,
month=month,
)
data = {
'user':user,
'name':obj.name,
'price':obj.price,
'quantity':obj.quantity,
'month':month
}
form = ProductForm(data=data)
yield form
def test_product_form_with_data(product):
assert True is not None
assert True == product.is_valid()
Below is what is am getting from the terminal.
Traceback error.
_______________________________________________________________________________________ test_product_form_with_data ________________________________________________________________________________________
product = <ProductForm bound=True, valid=False, fields=(name;price;quantity;month)>
def test_product_form_with_data(product):
assert True is not None
> assert True == product.is_valid()
E assert True == False
E -True
E +False
tests/test_forms.py:42: AssertionError
models.py
class Product(models.Model):
month = models.ForeignKey(Month, on_delete=models.CASCADE, related_name='months')
user = models.ForeignKey(User, on_delete=models.CASCADE, related_name='users')
name = models.CharField(max_length=30)
slug = models.SlugField(max_length=30, db_index=True, blank=True)
price = models.DecimalField(max_digits=10, decimal_places=2)
quantity = models.PositiveSmallIntegerField(default=0)
created = models.DateTimeField(default=datetime.datetime.now())
is_active = models.BooleanField(default=True)
forms.py
class ProductForm(ModelForm):
class Meta:
model = Product
fields = [
'name',
'price',
'quantity',
'month',
]
I would really appreciate a feedback to help me understand what I am doing wrong trying to test this form with data while using fixture.
The problem is that month is a ForeignKey so you need to pass the object ID in data, something like this:
data = {
'user':user,
'name':obj.name,
'price':obj.price,
'quantity':obj.quantity,
'month':month.pk,
}
You would have the same problem with user but actually user is not in the list of fields handled by your form (look at ProductForm.Meta.fields), so it will be ignored. You can decide to either removed it from data or add it to fields.
I'm trying to create a profile for clinics where I can show doctors under each specialization. I want to show the specialization with most doctors to least doctors.
For instance:
Dentists:
Names of all dentists (7)
Pediatricians
Names of pediatricians (4)
OB/GYN
Names of all obgyns (2)
models.py
class Doctor(models.Model):
name = models.CharField(max_length=1300)
specialization = models.ForeignKey(Specialization, related_name = "doctor_specialization")
sub_specialization = models.ForeignKey(Specialization, related_name = "doctor_subSpecialization", null = True, blank = True)
clinic = models.ForeignKey(Clinic)
class Clinic(models.Model):
name = models.CharField(max_length=500)
slug = models.CharField(max_length=200, blank = True, null = True, unique = True)
contact_no = models.IntegerField()
class Specialization(models.Model):
name = models.CharField(max_length=30)
views.py
def clinicProfile(request, slug):
clinic = get_object_or_404(Clinic, slug=slug)
doctors = Doctor.objects.all().order_by('-netlikes')
d.update({'clinic': clinic, 'doctors': doctors, })
return render(request, 'm1/clinicprofile.html', d)
It's simple.Instead of using ('-netlikes') just use ('netlikes') and it should work. Your function should look like this.
def clinicProfile(request, slug):
clinic = get_object_or_404(Clinic, slug=slug)
doctors = Doctor.objects.all().order_by('netlikes')
You need backward annotation, and it will look like:
from django.db.models import Count, Min, Sum, Avg
specialization = Specialization.objects.annotate(Count('doctor'))
I have such a model, in my django application. I want to draw only one field of this model and put them in the view. My solution below does not work:
obj = Text.objects.get(subsID)
My model
result = braintree.Subscription.create({
"payment_method_token": payment_method_token,
"plan_id": "67mm"
})
subscription_id = result.subscription.id
class Text(models.Model):
title = models.CharField(max_length=255)
text = models.TextField()
date_from = models.DateTimeField('date from', blank=True, null=True)
date_to = models.DateTimeField('date to', blank=True, null=True)
subsID = models.CharField(default=subscription_id, max_length=255)
def __unicode__(self):
return self.title
My view
def get_history(request):
subscription_id = Text.objects.filter(subsID)
history = braintree.Subscription.find(subscription_id)
return render(request, "sheet/history.html", {"history": history})
Generally, When filter or get, you have to put query inside it, like
subscription_id = Text.objects.filter(fieldname="searchterm")
This will return a queryset.So to view this
subscription_id.values() #returns a list of objects(dicts)
If you want to get only subsID
subscription_id.values("subsID")
This also return you list which contains
[{"subsID":"value"}, {"subsID":"value"} ....]
If you want to get only values
subscription_id.values_list("subsID", flat=True)
This will return like
["value", "value", ....]
You have to equal subsID to the value you want to find.
subscription_id = Text.objects.filter(subsID=<your subscrition id variable>)
pay attention this will return a list []
subscription_id = Text.objects.get(subsID=<your subscrition id variable>)
This will return an object
Link
You can't use the model in the view, you need to use the ModelForm or Form.
Once you use that one, you can specify which field is active or not or simply setting the attribute in the ModelForm,
exclude=['paramiter_name']
and it's done.
Good luck.
How to create an object for a Django model with a many to many field?
From above question i come to know we can save Many to Many field later only.
models.py
class Store(models.Model):
name = models.CharField(max_length=100)
class Foo(models.Model):
file = models.FileField(upload_to='')
store = models.ManyToManyField(Store, null=True, blank=True)
views.py
new_track.file = request.FILES['file']
new_track.save()
And file uploading working fine then later i modify my code to add store then i am here...
Now i am sure db return id's here. Then i tried with my below code but that's given me error only
x = new_track.id
new = Foo.objects.filter(id=x)
new.store.id = request.POST['store']
new.save()
ok so the error here is 'QuerySet' object has no attribute 'store'
And also i tried with add that's now working either.
So the question is how to save()
the right way of saving objects with manytomany relations would be:
...
new_track.file = request.FILES['file']
new_track.save()
new_store = Store.objects.get(id=int(request.POST['store']))
new_track.store.add(new_store)
As of 2020, here's my approach to saving ManyToMany Field to a given object.
Short Answer
class HostingRequestView(View):
def post(self, request, *args, **kwargs):
form = VideoGameForm(request.POST)
if form.is_valid():
obj = form.save(commit=False)
obj.updated_by = request.user
obj.save()
selected_categories = form.cleaned_data.get('category') #returns list of all selected categories e.g. ['Sports','Adventure']
#Now saving the ManyToManyField, can only work after saving the form
for title in selected_categories:
category_obj = Category.objects.get(title=title) #get object by title i.e I declared unique for title under Category model
obj.category.add(category_obj) #now add each category object to the saved form object
return redirect('confirmation', id=obj.pk)
Full Answer
models.py
class Category(models.Model):
title = models.CharField(max_length=100, null=True, unique=True)
class VideoGame(models.Model):
game_id = models.AutoField(primary_key=True)
name = models.CharField(max_length=50, blank=False, null=False)
updated_by = models.ForeignKey(settings.AUTH_USER_MODEL, blank=False, on_delete=models.CASCADE)
category = models.ManyToManyField(Category) #ManyToMany Category field
date_added = models.DateTimeField(auto_now_add=True, verbose_name="date added")
forms.py ModelForm
class VideoGameForm(forms.ModelForm):
CATEGORIES = (
('Detective', 'Detective'),
('Sports', 'Sports'),
('Action', 'Action'),
('Adventure', 'Adventure'),
)
category = forms.MultipleChoiceField(choices=CATEGORIES, widget=forms.SelectMultiple())
class Meta:
model = VideoGame
fields = ['name', 'category', 'date_added']
views.py on POST
class HostingRequestView(View):
def post(self, request, *args, **kwargs):
form = VideoGameForm(request.POST)
if form.is_valid():
obj = form.save(commit=False)
obj.updated_by = request.user
obj.save()
selected_categories = form.cleaned_data.get('category') #returns list of all selected categories e.g. ['Sports','Adventure']
#Now saving the ManyToManyField, can only work after saving the form
for title in selected_categories:
category_obj = Category.objects.get(title=title) #get object by title i.e I declared unique for title under Category model
obj.category.add(category_obj) #now add each category object to the saved form object
return redirect('confirmation', id=obj.pk)
URL path for redirect
urlpatterns = [
path('confirmation/<int:id>/', Confirmation.as_view(), name='confirmation'),
]
I hope this can be helpful. Regards
new.stores.all()
returns all stores linked to the object.
Maybe:
Change Foo to Tracks
Tracks.objects.filter(id=x) to Tracks.objects.get(id=x)
Let me know how it goes
why this confusion so much.. you are getting the id there then, call the store like
new_track.save()
new_track.store.add(request.POST['store'])