I have a model with 3 fields (name, url, date). How can I get url in my view and put it inside method?
sites = Site.objects.all().order_by('date')[:3]
I need to get host from url (http://www.example.com to example.com). I have a class for this task:
class SiteThumb():
def get_site_thumb(self, url):
host = urlparse(url).hostname
if host.startswith('www.'):
host = host[4:]
return(host)
I would like to use it later in my template (something similar to {{ site.url }} but with use of variable 'host' related to particular 'site' object).I can not deal with it. I can with another view where is only one site:
def site(request, category_slug, subcategory_slug, id):
There is id which I can simply assign to particular object. In my base view
def index(request):
I have to load a couple of objects. Thanks for any clues.
One approach is model methods.
For eg. Site is a model in which you have the said three fields url, name and date. Now you can define a model method for Site model which you can access in template. It can be done in this way.
class Site(models.Model):
url = field
name = field
date = field
def hostname(self):
#It is copy paste of your implementation
host = urlparse(url).hostname
if host.startswith('www.'):
host = host[4:]
return host
In your template on every Site instance this method can be accessed as {{ site.hostname }}.
Related
I have a django page that displays a list of links. Each link points to the detail page of the respective object. The link contains the pk/id of that object (something like ../5/detailObject/). The list is generated on the backend and has some filtering baked into it, e.g. only generate a link if that object has state x, etc.
Clicking on the links works, but users can still manipulate the url and pass a valid link with an incorrect state (a wrong pk/id is being handled with the get or 404 shortcut).
What is the best practice for handling this kind of scenario with django? Should that kind of filtering be placed in the object's model class instead of using function-based views as I do now?
Function based view:
If you want to restrict a set of objects to a particular user (for instance a user's orders), then you would need to set up the Order model to foreign key to the User model and then look up the order by both id and user:
views.py:
def get_order(request, id=0)
if request.method == 'GET':
try:
order = Order.objects.get(user=request.user, pk=id)
except Order.DoesNotExist:
return redirect(...)
And set up a url to handle:
url(r'^order/(?P<id>\d+)/$', views.get_order, name='get_order_by_id'),
As far as adding a slug field on the model after the fact, set up a second url:
url(r'^order/(?P<slug>[\w-]+)/$', views.get_order, name='get_order_by_slug')
And change the above view logic to first do a lookup by pk if pk is greater than 0 and then redirect back to the function using the slug from the looked up order (this assumes all looked-up records have slugs):
def get_order(request, slug='', id=0)
if request.method == 'GET':
try:
if id > 0:
order = Order.objects.get(user=request.user, pk=id)
return redirect(reverse('get_order_by_slug'), permanent=True, slug=order.slug)
order = Order.objects.get(user=request.user, slug=slug)
except Order.DoesNotExist:
return redirect(...)
You should also put unique=True on the slug field and ensure that the user is authenticated by placing the #login_required decorator on your view.
To restrict orders by a particular status, you could:
Create a set of statuses for your Order model, and then you could:
Pass a value for a kwarg in the view when you filter, or
Create a custom manager on the Order model
There are several ways you could create your statuses:
as a set of choices on the Order model
use the SmartChoices library
as a database field
If you create choices on the Order model, it could be something like this:
class Order(models.model):
STATUSES = (
('PLCD', 'Placed'),
('INTR', 'In Transit'),
('DLVR', 'Delivered')
)
status = models.CharField(max_length=4, default='', choices=STATUSES)
An acquaintance who is a very seasoned Django professional told me about the SmartChoices library. I have not used it yet but would like to try it at some point. The database field option would be my least preferred way of doing this because that seems to me like moving programming variables into the database; however, it would work.
I'm using Django 2.0 type of urls, and I have urls with multiple variables in them, with the same name. I'm using also ClassBasedView
path('/companies/<int:pk>/products/<int:pk>/', AccountCompanyProductDetailView.as_view()
I'm using pk because is the primary key and CBV will know how to use it (similar for other Model fields).
If I use other names, CBV will not know what to search.
In a CBV how can I get the parameters and know which is which. ?
How Django knows pk from which Model I need in each position ?
Django does not know how to handle this. You need to rename your parameters and access them in your CBV.
This could look like the following:
urls.py:
path('/companies/<int:pk1>/products/<int:pk2>/', AccountCompanyProductDetailView.as_view())
views.py:
class AccountCompanyProductDetailView(DetailView):
model = Product
def get_object(self):
pk1 = self.kwargs['pk1']
pk2 = self.kwargs['pk2']
company = get_object_or_404(Company, pk=pk1)
product = get_object_or_404(Product, pk=pk2)
return product
You would need to do this in other views too. Override the according methods like get_queryset. Access the kwargs as shown above.
I have a form with some fields. I want to display all fields in form except two. However one field data needs to be displayed.
I am able to get the form but not able to retrieve the data from DB to display.
Model.py
class Company(models.Model):
STATUS_CHOICES=(
('service','service'),
('product','product'),
)
user=models.OneToOneField(settings.AUTH_USER_MODEL)
company_name=models.CharField(max_length=250)
company_address=models.CharField(max_length=250)
Company_telephone=models.CharField(max_length=250,blank=True)
company_email=models.CharField(max_length=250,blank=True)
company_website=models.CharField(max_length=250,blank=True)
VAT=models.CharField(max_length=250,blank=True)
Service_Tax=models.CharField(max_length=250,blank=True)
company_PAN=models.CharField(max_length=250,blank=True)
company_bankdetails=models.CharField(max_length=250,blank=True)
invoice_type=models.CharField(max_length=250,choices=STATUS_CHOICES,default='service')
def __str__(self):
return 'self.user.company_name'
forms.py
class companyeditform(forms.ModelForm):
class Meta:
model=Company
exclude = ('user','company_name',)
views.py
#login_required
def companyadd(request):
if request.method == 'POST':
company_form=companyeditform(instance=request.user.company,data=request.POST)
if company_form.is_valid():
new_form=company_form.save(commit=False)
new_form.save()
return render(request,'account/dashboard.html',{'section':'addcompany'})
else:
company_form=companyeditform(instance=request.user.company)
company_details=Company.objects.get(user=request.user.company)
return render(request,'account/company.html',{'company_form':company_form})
When form is displayed everything works as planned. However not getting company_name.
Using this query to get company name.
company_details=Company.objects.get(user=request.user.company)
Django gives following error:
Cannot query "self.user.company_name": Must be "User" instance.
In this query company_details=Company.objects.get(user=request.user.company) you are trying to get the company of a particular user. But in the statement, you are comparing user=request.user.company, both are two different types (User is the authuser model and request.user.company is the Company model). You cannot do this in the query.
company_details=Company.objects.get(user=request.user) This statement will solve the issue. And also you can do
company_details=request.user.company because the association is OneToOne.
The reason you are getting that error, is because you are trying to fetch a Company by filtering it out the company that matches the current user, but you are passing in the actual company object:
company_details=Company.objects.get(user=request.user.company)
# ^^^^^^^
You can fix the line, by doing this:
company_details=Company.objects.get(user=request.user)
But you already have the correct object, in request.user.company, you don't need to fetch it again, simply:
company_details = request.user.company
print(company_details.company_name)
In fact, since you are using the render shortcut, you don't even need to do this step, as the request object will be available in your template, so all you need to do really is:
Company: {{ request.user.company.company_name }}
Finally, you should always redirect after a POST request (see this article on wikipedia for the details).
request.user might be a class like AnonymousUser. Do some extra processing to ensure that request.user is the type provided by django.contrib.auth.get_user_model().
Is there any built-in or 3rd party app for custom styled urls?
I'd like to have custom urls such as:
example.com/article-type/article-name-2015-24-12
Where article-type would be a created from a foreign key and at the end of the url there would be the published date.
And in templates I'd call them using {% url 'article' article.pk %}. (So in the future when my boss decides to change the url structure I don't have to change it everywhere)
Is there anything like that? If not could anyone kick me to the right direction how to implement a such feature?
You could build the URL on the model, overriding the get_absolute_url() method.
Something like this
def Something(models.Model):
name = models.CharField(max_length=100)
slug = models.SlugField()
created = models.DateTimeField()
article_type = models.ForeignKey(ArticleTypes)
def get_absolute_url(self):
return '/{}/{}-{}-{}-{}'.format(
self.article_type, self.slug, self.created.year,
self.created.month, self.created.day)
And in the template, you'd use
{{ something.name }}
Say I have an Model which displays as follows.
class Opt(models.Model):
optID = models.CharField()
availabiltities = models.ManyToManyField(Available)
lastdatemodified = models.DateTimeField()
....
....
Also, opt_ID is not the primary_key
I want to be able to display all the field with respect to that opt_id in the html template. I have a page which displays all the Opt_id for that model. And each Opt_ID is a link which is supposed to display all the fields as I mentioned before...
In views.py I am currently writing,
def Optschedule(request, opt_id = 1):
return render_to_response('show.html', {'OptSchedule', Opt.objects.filter(optID=Opt_id)})
In show.html
{% for entries in OptSchedule %}
{{entries.lastdatemodified}}
{{entries.availabilities}}
{% endfor %}
I guess, i am not understanding how do we pass arguments to the view function so that it uses those arguments for the queryset in views.
Thanks.
I understood your question, but you're missing some basics of Django
You can pass the arguments to your view in your request, configuring properly your urlconf.
But first, let's use lowercase for function names, as preconized by Python PEP8:
Function names should be lowercase, with words separated by underscores as necessary to improve readability.
def opt_schedule(request, opt_id):
opt_schedule = Opt.objects.get(id=opt_id)
return render_to_response('show.html', {'OptSchedule': opt_schedule})
You're passing opt_id to your view, and this opt_id came from your urlconf, suppose:
(r'^show/(\d+)/$', opt_schedule),
this urlconf says that you're passing a decimal integer for your view opt_schedule, besides the request object. When you call www.example.com/show/1/, the view opt_schedule is called and receive request object and the decimal 1. Inside your view function, you're querying for Opt object that have the id (or pk) = 1, and passes it to your context with the name 'OptSchedule'
Now you can access your object attributes in your template, like:
{{ OptSchedule.lastdatemodified }}