I would like to know this method must be to work up due to I've tried to implement but I could not.
Actually I've tried entering to the shell through
python manage.py shell
c=Category.objects.get(pk = 3)
c.get_absolute_url
#I got <bound method Category.get_absolute_url of <Category: Category2>>
c.get_absolute_url()
#It Doesn't work
I want to implement it within another model named Article that it's a foreign key to Category model
My intention is to have a method in Article like
def get_abs_url(self):
c=Category.objects.get(pk=self.category)
return c.get_absolute_url() + '/' + self.slug
Something like that
Perhaps you could supply more information regarding your models and what you are trying to achieve. Something like this might help:
models.py
class Article(models.Model):
category = models.ForeignKey(Category, related_name='article')
...
Where ever you return a queryset in views:
def get_context_data(self, **kwargs):
context = super(ArticleView, self).get_context_data(**kwargs)
context['articles'] = Article.objects.all().select_related('category')
return context
In templates:
{% for article in articles %}
{% for category in article.category %}
{{ category.get_absolute_url }}/{{ category.slug }} # this will return a string: abs_url/slug
{% endfor %}
{% endfor %}
Read about select_related here: https://docs.djangoproject.com/en/dev/ref/models/querysets/#select-related
You could also take a look at implementing Managers: https://docs.djangoproject.com/en/dev/topics/db/managers/#django.db.models.Manager
Finally, I overcame this problems throw the follow solution, first of all, my intention have always been to get something like that
/c/slug_category_parent/slug_first_children/.../last_children.
I've resolved throw this solution in settings.py:
cat_url= lambda c: cat_url(c.parent) + '/' +c.slug if c.parent else '/c/'+ c.sl
ABSOLUTE_URL_OVERRIDES = {
'categories.category': lambda c: cat_url(c),
}
Related
I have this function inside my model that is not appearing when I try to run the server. I think I am accessing the method correctly but when I tried writing print("ENTER") inside the total_balance() function, nothing showed up which makes me think that it's not even entering the method at all. Oddly, the function works if I take out the search functionality.
model.py
class Profile(models.Model):
user = models.OneToOneField(User, on_delete=models.CASCADE)
def total_balance():
transaction_list = Transaction.objects.filter(user=User)
total_balance_amount = 0
for transaction in transaction_list:
if transaction.category=='Income':
total_balance_amount += transaction.amount
elif transaction.category=='Expense':
total_balance_amount -= transaction.amount
return total_balance_amount
views.py
def profile(request):
if request.method == 'GET':
query = request.GET.get('q')
if query and query!="":
results = Transaction.objects.filter(Q(tag__icontains=query))
else:
results = Transaction.objects.all()
transactions = {
'transactions' : results,
}
profile = {
'profile' : Profile.objects.all()
}
return render(request, 'users/profile.html', transactions, profile)
template.py
<h5 class="card-title">Total Balance</h5>
<p class="card-text">₱{{ profile.total_balance }}</p>
Can someone please help me identify the reason this is not working and how I might be able to fix it? Thank you.
There are at least four things wrong here.
Firstly, for some reason you are passing two separate dictionaries to render. That doesn't work; you need a single dictionary with multiple entries.
context = {
'transactions' : results,
'profile' : Profile.objects.all()
}
return render(request, 'users/profile.html', context )
Secondly, profile - despite the singular name - is a queryset of all profiles. You would need to iterate through it in your template:
{% for prof in profile %}
<p class="card-text">₱{{ prof.total_balance }}</p>
{% endfor %}
Ideally, you would use a more appropriate name for the context variable, ie profiles.
Next, your total_balance method itself has two issues. Firstly, any method in Python needs to take the self parameter. And secondly, you need to use that parameter to access the value of the user field, not the class User. So:
def total_balance(self):
transaction_list = Transaction.objects.filter(user=self.user)
although note that that second line could be more easily written:
transaction_list = self.user.transaction_set.all()
I would like to show possible choices from ManyToManyField (which I have in Homes model) in the Owners form. I have Owners <--Many2Many--> Homes with custom class HomesOwners. In Homes it works out of the box, I don't know how to make it work in Owners.
I am using Django 2.2.4 with Bootstrap 4 and Postgresql. I started my project based on django-bookshelf project (also just Django and Bootstrap4). I do not use any render. Comment in django-bookshelf project mentioned How to add bootstrap class to Django CreateView form fields in the template?, so I stick to that if it comed to forms.
I'm pretty new to Python (so Django too) and web technologies in general. I googled dozen of different questions/answers but I couldn't find any nice explanation of what is what and how to use it in real life. Most of them ended up with basic usage.
I did some experimentation on my own, but no success so far...
Here is the code
I have two models - Homes/models.py and Owners/models.py
Homes/models.py:
class Homes(models.Model):
id = models.AutoField(primary_key=True)
# other fields
some_owners = models.ManyToManyField(Owners, through='HomesOwners', through_fields=('id_home', 'id_owner'), related_name='some_owners')
# end of fields, some other code in the class like "class Meta" etc.
class HomesOwners(models.Model):
id = models.AutoField(primary_key=True)
id_home = models.ForeignKey(Homes, models.DO_NOTHING, db_column='id_home')
id_owner = models.ForeignKey('owners.Owners', models.DO_NOTHING, db_column='id_owner')
Owners/models.py do not have anything special, no imports from my Homes/models.py etc.
and my forms:
Homes/forms.py:
class HomesForm(forms.ModelForm):
def __init__(self, *args, **kwargs):
super(HomesForm, self).__init__(*args, **kwargs)
self.fields['some_field_from_homes_model'].widget.attrs = {'class': 'form-control '}
#
# --> no need self.fields for M2M, Django does the work
#
# but I tried also and have a --> Question 2
# self.fields["some_owners"].widget = forms.widgets.CheckboxSelectMultiple()
# self.fields["some_owners"].queryset = HomesOwners.objects.all()
Without any code as "self.fields" for M2M field, Django is able to generate for me list of owners.
Question 1
I would like to get list of Homes in my OwnersForms.
I do not know what to add. I assume that I cannot add
# Owners/models.py
some_homes = models.ManyToManyField(Homes, through='HomesOwners', through_fields=('id_home', 'id_owner'), related_name='some_homes')
because of circular import, am I right?
How do I get my Homes list using self.fields?
What do I need to add to my code?
Question 2
When I've added
# Homes/forms.py
self.fields["some_owners"].widget = forms.widgets.CheckboxSelectMultiple()
self.fields["some_owners"].queryset = HomesOwners.objects.all()
I got
<!-- html page -->
HomesOwners object (1)
HomesOwners object (2)
<!-- and so on... -->
How can I just list Owners?
How to filter/order them so first they would appear Owners not connected to any Home?
Question 3
class HomesOwners(models.Model):
id = models.AutoField(primary_key=True)
id_home = models.ForeignKey(Homes, models.DO_NOTHING, db_column='id_home')
id_owner = models.ForeignKey('owners.Owners', models.DO_NOTHING, db_column='id_owner')
def __str__(self):
return pass #return something
I can't get my head around this. This class connects Homes and Owners. When I'm thinking of Homes I would like to return Owners and vice versa. So it should return different things depending on what object we are using (home or owner). I think this is connected to my 2nd question about:
HomesOwners object (1)
Also...
In homes.html I'm using my M2M like that:
{% for owner in homes.homesowners_set.all %}
{{ owner.id_owner.id }}
{% endfor %}
I would like to write something similar to my owners.html and list homes. This is connected to my previous question, I would like to have full answer if that's possible.
EDIT
With the answer given to me I was able to add Homes to OwnerUpdate view. I have views like that:
owners/views.py
# List View
class OwnersList(ListView):
model = Owners
# Detail View
class OwnersView(DetailView):
model = Owners
# Create View
class OwnersCreate(CreateView):
model = Owners
form_class = OwnersForm
# Setting returning URL
success_url = reverse_lazy('owners_list')
# Update View
class OwnersUpdate(UpdateView):
model = Owners
form_class = OwnersForm
success_url = reverse_lazy('owners_list')
# Delete View
class OwnersDelete(DeleteView):
model = Owners
success_url = reverse_lazy('owners_list')
What change do I need to make to be able to show in OwnersList Homes they own?
In Homes DetailView I am able to show Owners. I would like to do the same for Homes' DetailView and Homes ListView.
I don't really get it what you asking for,
but if I understand your question correctly,
I assume you want to add Homes list (not HomesOwners list) into your Owners form, right?
you can add extra field in your form like this:
class OwnersForm(ModelForm):
# notice the queryset is 'Homes' not 'HomesOwners'
homes = forms.ModelMultipleChoiceField(queryset=Homes.objects.all(), widget=forms.CheckboxSelectMultiple)
class Meta:
model = Owners
fields = ('homes', 'your_other_fields',)
# then you can access in init function too if you want
def __init__(self, *args, **kwargs):
super(OwnersForm, self).__init__(*args, **kwargs)
self.fields['homes'].required = False
then, since it using CheckboxSelectMultiple widget, you can iterate it in your html template like this:
{% for key, value in your_form.homes.field.choices %} <!-- notice '.field.'-->
{{ key }} = {{ value }}
{% endfor %}
you probably need to create custom save too for your form.
for your question 3, it is not about the form?
If you want to show HomesOwners, you are already doing right.
{% for owner in homes.homesowners_set.all %}
{{ owner.id_owner.id }}
{% endfor %}
but it will work if that homes is only 1 object.
if homes is a queryset, you have to iterate it first
{% for home in homes %}
{% for owner in home.homesowners_set.all %}
{{ owner.id_owner.id }}
{% endfor %}
{% endfor %}
sorry if I misunderstanding your questions,
maybe you can provide your views.py too, so I or others can help you more specific
I have this model:
class ModelName(models.Model):
def my_dict(self):
for i in range(n):
…#some code
context_a = {‘a’: a}
return context_a
I need to take context into view like this:
from .models import ModelName
class ViewName
model = ModelName
template_name = ’template_name.html’
def context_b(request):
context_b = ModelName.objects.get(context_a=context_a) #here I want to get context_a as a dictionary and pass it to context_b for further operations. I know that my syntax here is not correct.
return render(request, self.template_name, context_b)
If I do it, I get
Method Not Allowed: /
[18/Nov/2018 12:40:34] "GET / HTTP/1.1" 405 0
I would like to know how to do it correctly, and also which specific resource (documentation and/or article) should I read/learn to understand my problem.
I would appreciate any help.
I think you are not subclassing proper class based view here.
The error you are getting is that, you are calling get method, but the View you have provided does not support that. For simplistic purpose, lets use DetailsView which supports get request, so you can try like this:
class YourView(DetailsView):
template_name = 'template_name.html'
model = MyModel
def get_context_data(self, **kwargs):
context = super(YourView, self).get_context_data(**kwargs)
context_a = self.object.my_dict() # here you will get the dictionary from model in view
# by the way, you can also access the your model object from context via context['object'] and in template via {{ object }}
return context
And access dictionary of the template like this:
{% for k, v in object.my_dict.items %}
{{ k }} - {{ v }}
{% endfor %}
Also the Url
#urls
path('/someview/<int:pk>/', YourView.as_view(), name="your_view"),
I'm a little rusty with django.
I'm wondering if anyone can tell me how I count the db objects from this query:
UserEnteredTld = Tld.objects.filter(FKtoClient=request.user, auth=0)
I used to do:
UserEnteredTld = Tld.objects.filter(FKtoClient=request.user, auth=0).count()
In the template (with the var):
{% if UserEnteredTld %}
<h3>I have Tld's</h3>
{% endif %}
the view:
UserEnteredTld = Tld.objects.filter(FKtoClient=request.user, auth=0).count()
UserAuthTld = Tld.objects.filter(FKtoClient=request.user,auth=1).count()
return render(request, 'accounthome.html', {
'UserEnteredTld':UserEnteredTld,
'UserAuthTld':UserAuthTld
})
model
class Tld(models.Model):
auth = models.BooleanField(default=False)
FKtoClient = models.ForeignKey(User)
but, this appears to not be outputting anything. (I verified actual rows exist...)
To be clear: I'm simply trying to count the number of rows for the Tld table where a ForeignKey exists for the logged in user and the auth=0.
Don't use count for that. Use exists (docs).
user_entered_tld = Tld.objects.filter(FKtoClient=request.user, auth=False).exists()
{% if user_entered_tld %}
<h3>I have Tld's</h3>
{% endif %}
Some notes:
Django latest version is 1.7 (on beta). It's impossible you're using 2.6.2 (that seems like a Python version)
Don't camel-case your variables. Use user_entered_tld instead of
UserEnteredTld. It's a good Python convention.
What is the best way to create get_absolute_url function for Comment if I need url like this: "/article_url#comment-id"?
My models:
class Article(models.Model):
url = models.CharField()
def get_absolute_url(self):
return reverse('article-detail', args=[self.url])
class Comment(models.Model):
related_article = models.ForeignKey(Article)
My variants:
1) very simple, but in this case django will fetch all fields of article, it's terrible for views like "latest 10 comments" on main page:
u = self.related_article.get_absolute_url()
return ''.join([u, '#comment-', str(self.pk)])
2) in this case, function will be independent of Article class changes, but django will fetch pk in first query and url in second query:
u = Article.objects.filter(pk=self.related_article_id) \
.only('pk') \
.get() \
.get_absolute_url()
return ''.join([u, '#comment-', str(self.pk)])
3) in this case, field 'url' was hardcoded, but django will fetch pk and url in one query:
u = Article.objects.filter(pk=self.related_article_id) \
.only('url') \
.get() \
.get_absolute_url()
return ''.join([u, '#comment-', str(self.pk)])
I am not sure if you are gaining much by storing the url in your Article model and providing a get_absolute_url, however, you do not need to worry about trying to explicitly support anchor tags in your URL; just make sure that you are setting the id properly in your tags in the template.
# views.py
def article_detail(request, article_id):
# Proper exception try/except handling excluded:
article = Article.objects.get(id=article_id)
article_comments = Comment.objects.filter(related_article_id=article_id)
return render_to_response('article_detail.html', {'article': article,
'article_comments': article_comments}
# article_detail.html
{% for article_comment in article_comments %}
<div id='comment-{{article_comment.id}}'>
{# Comment information here. #}
</div>
{% endfor %}
If you are interested in hyperlinking a summary list of comments back to the original article where the comment appeared, then you are probably best defining a get_absolute_url function for the Comment model as well.
Edit: Let's say you are showing the 10 latest comments on your main page, where the actual article is not appearing:
# views.py
def main(request):
# Assumes timestamp exists for comments.
# Note: This query will get EXPENSIVE as the number of comments increases,
# and should be replaced with a better design for a production environment.
latest_article_comments = Comment.objects.all().order_by('creation_date')[:10]
render_to_response('main.html', {'latest_article_comments': latest_article_comments})
# main.html
{% for article_comment in article_comments %}
{{article_comment.user_comment}}
{% endfor %}