So I have two models Field and Sensor which have a OneToMany connection. Im creating a page where I have all the fields and whenever i click on one i get its respective sensors. I've made 4 test sensors (3 of them are on Field1, 1 on Field2) but its printing first one to first field and 2nd one to 2nd field maybe because of the pk parameter. Any clue how to fix that ?
class Field(models.Model):
friendly_name = models.CharField(max_length=24, blank=True)
soil_type = models.CharField(max_length=24, choices=SOIL_TYPES, blank=True)
cultivation = models.CharField(max_length=128, choices=CULTIVATIONS, blank=True)
class TreeSensor(models.Model):
field = models.ForeignKey(Field, on_delete=models.CASCADE)
datetime = models.DateTimeField(blank=True, null=True, default=None)
sensor_name = models.CharField(max_length=200, blank=True)
longitude = models.DecimalField(max_digits=22, decimal_places=16, blank=True, null=True)
latitude = models.DecimalField(max_digits=22, decimal_places=16, blank=True, null=True)
View :
def detail(request, field_id):
try:
sensor = models.TreeSensor.objects.get(pk=field_id)
except models.TreeSensor.DoesNotExist:
raise Http404("No sensors for this field")
return render(request, 'dashboard/detail.html', {'sensor': sensor})
html:
<h1> {{ field.friendly_name}}</h1>
{% for sensor in field.treesensor_set.all %}
{{treesensor.sensor_name}}
{%endfor%}
I'm not sure what does this line will print out? and what is "models" in that case mean!
models.TreeSensor.objects.get(pk=field_id)
however, if you passed field_id which means the id of the Field model so, I think you can replace that filtering instead:
TreeSensor.objects.filter(field__pk=field_id)
Yeah that seemed to do the trick I also changed my template
{% for sensor in sensor %}
<ul>
<li>{{ sensor.sensor_name}}</li>
</ul>
{%endfor%}
and view :
def detail(request, field_id):
try:
sensor = models.TreeSensor.objects.filter(field__pk=field_id)
except sensor.DoesNotExist:
raise Http404("No sensors for this field")
return render(request, 'dashboard/detail.html', {'sensor': sensor})
I get the right sensors on the right fields but if a field is empty the http404 does not raise an error.
Maybe I'm doing something wrong with the does.not.exist?How to just check for an empty query and print out the corresponding text? Thanks
Related
Here i have a Model Recommenders:
class Recommenders(models.Model):
objects = None
Subject = models.ForeignKey(SendApproval, on_delete=models.CASCADE, null=True)
Recommender = models.CharField(max_length=20, null=True)
Status = models.CharField(null=True, max_length=8, default="Pending")
Time = models.DateTimeField(auto_now_add=True)
And another model Approvers:
class Approvers(models.Model):
objects = None
Subject = models.ForeignKey(SendApproval, on_delete=models.CASCADE, null=True)
Approver = models.CharField(max_length=20, null=True)
Status = models.CharField(null=True, max_length=8, default="Pending")
Time = models.DateTimeField(auto_now_add=True)
And my SendApproval model as:
class SendApproval(models.Model):
Subject = models.CharField(max_length=256)
Date = models.DateField(null=True)
Attachment = models.FileField(upload_to=get_file_path)
SentBy = models.CharField(null=True, max_length=100)
Status = models.CharField(null= True, max_length=8, default="Pending")
Now my problem is that I have to display the Subject and Attachment from SendApproval table only when all the recommender's Status in Recommenders table related to that subject is "Approved"
Don't know how can I know that...Thanks in advance...
Actually not have any Idea about the solution but the best answer will be appreciated...By the way, I am new to StackOverflow...So please let me know if there is some ambiguity in my question.
Offer two ways.
1.Here the Recommenders model is filtered by the Status='Approved' field. By the Subject field, which is associated with the primary model, I get access to the SendApproval fields.
Replace bboard with the name of the folder where your templates are placed.
I have this: templates/bboard which are in the application folder.
views.py
def info(request):
recomm = Recommenders.objects.filter(Status='Approved')
return render(request, 'bboard/templ.html', {'context': recomm})
urls.py
urlpatterns = [
path('info/', info, name='info'),
]
templates
{% for a in context %}
<p>{{ 'Subject' }} : {{ a.Subject.Subject }} {{ 'Attachment' }} : Link
{{ 'id SendApproval' }} : {{ a.Subject.id }}</p>
{% endfor %}
2.You can also filter by primary model by fields from a secondary model that is linked to the primary. Here, I passed in the filter the name of the model in lower case and the search field.
In the primary model, by default, a property is created to refer to the secondary model, this is the name of the model in lower case and the _set prefix. In the outer loop, all received rows of the primary model are sorted out, and in the inner loop, through recommenders_set.all(), we get the Status. As you can see it is Approved.
sa = SendApproval.objects.filter(recommenders__Status='Approved')
print(sa)
for i in sa:
for k in i.recommenders_set.all():
print('status', k.Status)
I recently found that too much SQL query optimization issue. django-debug-tool reported hundreds of similar and duplicate queries. So, I'm trying to figure out the best efficiency of Django ORM to avoid unnecessary Queryset evaluation.
As you see the below Store model, a Store model has many Foreign key and ManyToManyFields. Due to that structure, there are many code snippets doing the blow on HTML template files such as store.image_set.all or store.top_keywords.all. Everything starts with store. In each store detail page, I simply pass a cached store object with prefetch_related or select_related. Is this a bad approach? Should I cache and prefetch_related or select_related each Foreign key or ManyToManyField separately on views.py?
HTML templates
{% for img in store.image_set.all %}
{{ img }}
{% endfor %}
{% for top_keyword in store.top_keywords.all %}
{{ top_keyword }}
{% endfor %}
{% for sub_keyword in store.sub_keywords.all %}
{{ sub_keyword }}
{% endfor %}
views.py
class StoreDetailView(View):
def get(self, request, *args, **kwargs):
cache_name_store = 'store-{0}'.format(store_domainKey)
store = cache.get(cache_name_store, None)
if not store:
# query = get_object_or_404(Store, domainKey=store_domainKey)
query = Store.objects.all().prefetch_related('image_set').get(domainKey=store_domainKey)
cache.set(cache_name_store, query)
store = cache.get(cache_name_store)
context = {
'store': store,
}
return render(request, template, context)
models.py
class Store(TimeStampedModel):
categories = models.ManyToManyField(Category, blank=True)
price_range = models.ManyToManyField(Price, blank=True)
businessName = models.CharField(unique=True, max_length=40,
verbose_name='Business Name')
origin = models.ForeignKey(Origin, null=True, on_delete=models.CASCADE, blank=True)
ship_to = models.ManyToManyField(ShipTo, blank=True)
top_keywords = models.ManyToManyField(Keyword, blank=True, related_name='store_top_keywords')
sub_keywords = models.ManyToManyField(SubKeyword, blank=True, related_name='store_sub_keywords')
sponsored_stores = models.ManyToManyField(
'self', through='Sponsorship', symmetrical=False, related_name='sponsored_store_of_store')
similar_stores = models.ManyToManyField(
'self', through='Similarity', symmetrical=False, related_name='similar_store_of_store')
shortDesc = models.TextField(blank=True, verbose_name='Short Description')
longDesc = models.TextField(blank=True, verbose_name='Long Description')
returnPol = models.TextField(verbose_name='Return Policy', blank=True)
returnUrl = models.CharField(max_length=255, null=True, blank=True, verbose_name='Return Policy URL')
likes = models.ManyToManyField(settings.AUTH_USER_MODEL, blank=True, editable=False)
created_by = models.ForeignKey(settings.AUTH_USER_MODEL, editable=False, on_delete=models.CASCADE,
related_name='stores_of_created_by', null=True, blank=True)
updated_by = models.ForeignKey(settings.AUTH_USER_MODEL, editable=False, on_delete=models.CASCADE,
related_name='stores_of_updated_by', null=True, blank=True)
I really wouldn't advise custom caching/performance optimisation, unless it's a very last resort. Django has great docs on querysets and optimisation - if you follow those, it should be rare for you to experience major performance issues that require custom workarounds.
I think the issue here is that you're printing your objects in a template and hence calling their str() method. There's nothing wrong with this, but I'd check what variables you're using in your str() methods. I suspect you're referencing other models? I.e. the str() method in your image model (or whatever) is doing something like image.field.other_field. In this case, your query should look like:
queryset = Store.objects.prefetch_related('image_set__field')
Your final queryset may look like:
queryset = Store.objects.prefetch_related('image_set__field1', 'image_set__field2', 'top_keywords__field3', ...)
Note that you can still pass this into get_object_or_404 like so:
get_object_or_404(queryset, pk=<your_stores_id>)
Hope this helps.
I have 2 models -
class InsName(models.Model):
id = models.AutoField(primary_key=True)
name = models.CharField(max_length=30, verbose_name = "Insurer/Broker")
alias = models.TextField(max_length=80, blank=True)
def __str__(self):
return f'{self.name}, {self.alias}'
def get_absolute_url(self):
return reverse('insurer-detail', args=[str(self.id)])
class Development(models.Model):
id = models.AutoField(primary_key=True)
logno = models.CharField(validators=[RegexValidator(regex='^(SCTASK|CDLI)[0-9]{7}', message='Please enter a valid log number', code='nomatch')], max_length=13)
insurer = models.ForeignKey(InsName, on_delete=models.SET_NULL, null=True, blank=False, verbose_name="Client")
policy = models.ManyToManyField(Policy, blank=True)
on my template I am outputting a list of Developments but where insurer is output I just want the name part to output. I need to retain the alias as it is used in other templates that also calls in InsName.
I thought I could use a substring before comma method in the template but I cant see that such a thing exists. Is this possible? If not any tips on how I can achieve this is greatly appreciated!
Maybe you can do it like this using F (apart from comment of #dirkgroten):
queryset = Development.objects.all().annotate(insurer_name=F('insurer__name'))
And use it in template:
{% for item in queryset %}
{{ item.insurer_name }}
{% endfor %}
I am not able to create the object review using the CreateView I am not sure what I am doing wrong. Below is a brief intro
Intro: My Order history page is where a user can see all the items that he/she has bought. In the Order history page I have a button that lets the buyer leave a review for the seller. Below is the button
<a href="{% url 'accounts:review' username=item.made_by pk=item.pk %}">
<button class="text-success">Leave Review</button>
</a>
from here I get the items item.id and the sellers username
{% for item in order.items_in_this_order.all %} <!--models below -->
url(r'^(?P<username>[-\w]+)/(?P<pk>\d+)/review/$', views.ReviewCreate.as_view(), name='review'),
{% endfor %}
The url expresses correctly in the address bar when I click on leave a review. It then displays a form. where I enter feedback, ratings, feedback_image, feedback_video the rest of the fields are supposed to be made in the views.py. After I fill the form and hit submit. The url is still correct. But I get the below error
IntegrityError at /accounts/nikhil/10/review/
NOT NULL constraint failed: accounts_review.item_id
Request Method: POST
Request URL: http://127.0.0.1:8000/accounts/nikhil/10/review/
Django Version: 1.11
Exception Type: IntegrityError
Exception Value:
NOT NULL constraint failed: accounts_review.item_id
Below are the views.py this is inside the accounts app
class ReviewCreate(LoginRequiredMixin, CreateView):
model = Review
form_class = ReviewCreateForm
def form_valid(self, form):
self.object = form.save(commit=False)
self.object.review_from = self.request.user
print(self.object.review_from) #This prints
self.item = OrderItem.objects.get(pk=self.kwargs.get('pk'))
print(self.item) #This prints
self.object.review_for = User.objects.get(username=self.kwargs.get('username'))
print(self.object.review_for) #This prints
self.object.save()
return super().form_valid(form)
Below are the models.py for Review models
class Review (models.Model):
review_from = models.ForeignKey(User, on_delete=models.SET_NULL, null=True, related_name='review_from')
review_for = models.ForeignKey(User, on_delete=models.SET_NULL, null=True, related_name='review_for')
item = models.ForeignKey(OrderItem, related_name='items')
created = models.DateTimeField(auto_now_add=True)
feedback = models.TextField(blank=True, null=True)
feedback_image = models.ImageField(blank=True, null=True)
feedback_video = models.FileField(blank=True, null=True)
rating_choices = (
('1', 'One'), ('2', 'Two'), ('3', 'Three'), ('4', 'Four'), ('5', 'Five'),
('6', 'Six'), ('7', 'Seven'), ('8', 'Eight'), ('9', 'Nine'), ('10', 'Ten')
)
ratings = models.CharField(max_length=2, choices=rating_choices)
def __str__(self):
return 'Review from {} to {} for {}'.format(self.review_from, self.review_for, self.item.product)
Below are the models.py for OrderItem just in case
class OrderItem(models.Model):
product = models.CharField(max_length=350)
quantity = models.IntegerField()
price = models.DecimalField(max_digits=5, decimal_places=2, verbose_name='USD Price')
order = models.ForeignKey(Order, on_delete=models.CASCADE, related_name='items_in_this_order')
date = models.DateField()
time_from = models.TimeField()
time_to = models.TimeField()
made_by = models.ForeignKey(User, on_delete=models.SET_NULL, blank=True, null=True, related_name='product_by')
image = models.ImageField()
order_date = models.DateField(auto_now_add=True)
picked = models.ManyToManyField(User, blank=True, related_name='item_picked')
Your form_valid method is quite strange. Among other things, you set the item to self.item, which isn't used anywhere and certainly isn't set on the created instance. Additionally, you create and save the object there directly, but then call the superclass method which will do it again without your additions.
Instead you should set all these attributes on form.instance, then let the super method do the saving:
def form_valid(self, form):
form.instance.review_from = self.request.user
form.instance.item = OrderItem.objects.get(pk=self.kwargs.get('pk'))
form.instance.review_for = User.objects.get(username=self.kwargs.get('username'))
return super().form_valid(form)
In Django I have my app where I place information about countries and cities of these countries. This is my model.py file:
class Country(models.Model):
class Meta:
verbose_name_plural = u'Countries'
name = models.CharField(max_length=50)
slug = models.CharField(max_length=255)
description = models.TextField(max_length=10000, blank=True)
def __unicode__(self):
return self.name
class City(models.Model):
class Meta:
verbose_name_plural = u'Cities'
name = models.CharField(u'city', max_length=200)
slug = models.CharField(max_length=255, blank=True)
description = models.TextField(max_length=10000, blank=True)
country = models.ForeignKey('Country', blank=True, null=True)
def __unicode__(self):
return self.name
I have the detail view of my country, in this view there is a list of cities of this country(views.py):
def CountryDetail(request, slug):
country = get_object_or_404(Country, slug=slug)
list_cities = City.objects.filter(country=country)
return render(request, 'country/country.html', {'country':country, 'list_cities':list_cities})
this is my urls.py:
url(r'^(?P<slug>[-_\w]+)/$', views.CountryDetail, name='country'),
I want to create a url of cities which contain a slug of the country and a slug of the city, for example domain.com/spain/barcelona/.
So I created the detail view of the city, and it's looks like this:
def CityDetail(request, cityslug, countryslug):
country = Country.objects.get(slug=countryslug)
country_city = City.objects.get(country=country)
city = get_object_or_404(country_city, slug=cityslug)
return render(request, 'country/city.html', {'country':country, 'city':city})
Here is my urls.py for city detail:
url(r'^(?P<countryslug>[-_\w]+)/(?P<cityslug>[-_\w]+)$', views.CityDetail, name='resort'),
And this is how it looks like in my html file detail of the country that links to the cities:
<h1>{{country.name}}</h1>
<p>{{country.description}}</p>
<h2>Cities</h2>
{% for city in list_cities %}
<a href="/{{country.slug}}/{{city.slug}}">
<p>{{city.name}}</p>
</a>
{% endfor %}
But when I click on the link of the url of the city, I get error.
Object is of type 'City', but must be a Django Model, Manager, or QuerySet
In traceback i see that problem in CityDetail function in views.py file:
resort = get_object_or_404(country_city, slug=cityslug).
Hope you can help me with its problem. Thank You.
Yes, you can't call get_object_or_404 on an actual City object; the things that you can query are models or querysets, not instances. What do you think that call would do?
But actually the underlying problem is before that; your definition of country_city makes no sense. For a start, this is only currently working because you presumably have only one City in the country you're querying. When you have more than one, that line will fail with a MultipleObjectsReturned exception, because get can only return a single object.
You should remove that line altogether, and query the city directly from the country:
country = Country.objects.get(slug=countryslug)
city = get_object_or_404(City, country=country, slug=cityslug)