Building a django detailview and listview without using <int:pk> - python

I'm building a django app that displays a database of employees and their salaries. It uses a postgres database. I'm struggling to figure out how to build a DetailView without using a primary key for the url. I think using a slug may be the solution but I'm not sure how to implement that and haven't had much luck searching online.
My Listview for the list of all companies:
class AllCompanies(FormMixin, generic.ListView):
template_name = 'AllCompanies.html'
form_class = SearchForm
model = bigdatabase
queryset = bigdatabase.objects.order_by().values('company').distinct()
context_object_name = 'companies'
Example Database snippet, bigdatabase:
Company EmployeeName Salary
Alpha Jim 100000
Alpha Tim 125000
Beta Bim 90000
My list view displays all unique company names as intended. However, I'm not sure how to proceed and build a detailview to display more info on each unique company. I'd like to show things like number of employees, median salary, etc.
I've done something similar by building a detailview for employees, but that relied upon using their primary key in the url since each employee is unique. Since I have many entries for many companies in my database, how would I build a detailview and accompanying url structure to support that?
Any advice or pointers as to move this along would be greatly appreciated.

You can add a slugfield to your bigdatabase model. Try using the autoslugfield and set it to the company name like:
from django_extensions.db.fields import AutoSlugField
class bigdatabase(models.Model):
company = Models.Charfield()
slug = models.AutoSlugField(populate_from=['company']
......
This makes sure you company name will automatically be translated for use in the url. E.g. when you have spaces in the company name, using str:company will translate in weird characters for the space. Using in your url translates this to a -.
Naming your model field slug makes sure that your detailview get the slug field by default. See docs.
Your views will then look something like:
class CompanyDetailView(DetailView):
model = bigdatabase
template_name = '#path_to_template'
slug_url_kwarg = 'slug' # I believe this is done correctly by default but in case you change the field name.
In your url you can do something like mentioned above:
path('company/<slug>', views.CompanyDetailView.as_view())
Happy coding!

Not sure that I understood correctly, but I thought you can use something like this:
path('company/<str:name>', views.company_detail_view)

Related

Birthdays employee Django Model

I have a model with employees data, name, photo, date of birth and etc.
I'm trying to create a url that shows the birthdays of the employees where I can filter, if i click at one button, filter the birthdays of the day, another button, birthdays of the week and so on.
I'm don't know where I can work with the date of birth to generate theses "category".
I'm looking for ideas to implement these
Thanks in advance
When you ask,
... where I can work with the date of birth to generate theses 'category'
it sounds like you're asking about a view. Views are Python functions typically placed in a file called views.py.
Let's say you have a model Employee defined in your models.py with a field birthdate (among others):
# models.py
class Employee(models.Model):
employee = models.CharField(
help_text = 'Employee name'
)
birthdate = models.DateField(
help_text = "Employee's birthdate"
)
# other fields...
I'll further assume that you've run makemigrations and migrate on this model so that it has a table in your database (more on migrations). And of course, this won't work in the end unless you put actual data into that database, which is also covered in the docs.
Then in your views.py file, you can import this model and access its fields using code like
# views.py
from yourApp.models import Employee
def bday(request):
employees = Employee.objects.all()
for emp in employees:
bdate = emp.birthdate
# further logic with 'bdate', etc.
The docs have much more on how to access your data in view functions.
Once your view has loaded all of the data you'll want to display on the page, you'll combine that data with a template and use the URLconf settings in your urls.py file to map the bday() view function to whatever URL you want.
The interactivity you mention for applying filters would typically be done using JavaScript, otherwise you'll have to reload the page entirely every time the user changes a filter. That JavaScript would be written in a separate file and included in your template.
The Django docs are imperfect, but they'll certainly help you get a better idea of what you're looking for. In particular, I recommend the tutorial, which you should work through, and the basics of views

Stock code request application in Django & SQL

I have a material excelfile and it has different type of material.
Each category has start specific prefix like AB001 or BC001
I am planning to write a webservice for the request of this material stock codes.
But I need to import the my old database and i have stucked how can i implement this?
I have created a model in DJANGO like Materials, But i could not solve that if i import the my old excel file, the software how can understand the numbers will be correct.
It must be consecutively. Like ( AB001 , AB002, AC001,AC002,AZ001)
Thanks in advance!
Django ORM has an order_by() method. do you need something other than this?
The models meta class can allow for default order
models.py
class Material(models.Model):
material_stock_code = models.CharField(max_length=255)
class Meta:
ordering = ['material_stock_code']
The order_by() method can be used on any query
views.py
Material.objects.all().order_by('material_stock_code')
I would also recommend looking at django-rest-framework to make the API

Many to Many and Foreign Key relations in django admin

First my django knowledge is beginner level, so please be patient with me.
I am faced with a model relationship that I do not know how to handle. I have 3 models: Project, Location and SubLocation.
A project can have multiple locations and each location can have many sublocations. I have a many to many field for location in the Project model and a foreignkey field for location in the Sublocation model.
class Project(models.Model):
...
locations = models.ManyToManyField(Location)
class Location(models.Model):
name = models.CharField(max_length=250, unique=True)
class SubLocation(models.Model):
location = models.ForeignKey(Location)
name = models.CharField(max_length=100, unique=True)
In django admin, I am able to add multiple locations when creating a project(Using filter_horizontal). However, I also need the option to select sublocations based on an added location for the project being created. I did not know how to do it with the above approach.
I then removed the locations many to many field from the project model tried the approach below.
I created a ProjectLocation model and added it as an inline to the Project ModelAdmin to be able to add locations and sublocations when creating a project. The model that looks as follows:
class ProjectLocation(models.Model):
project = models.ForeignKey(Project)
location = models.ManyToManyField(Location)
sublocations = models.ManyToManyField(SubLocation)
However, the approach does not work as desired since you can add any sublocations irregardless of the locations added. What I would like is to be able to add locations and their relevant sublocations when creating a project.
I read through generic relations as another possible approach but still I did not know how to pull it off.
With my model structure, is that possible?
If True, what should I do to get the desired result?
If False, please recommend how I could change it.
I think if you use foreign key it will be easier for your case, and it will easy to use with the _set option from django.
Yes it is possible but it will not be dynamic (meaning that changing the value of location will not magically update themselves without first saving the change) which might be very unpractical.
You should use formfield_for_manytomany in your admin -> https://docs.djangoproject.com/en/1.8/ref/contrib/admin/#django.contrib.admin.ModelAdmin.formfield_for_manytomany
The easiest way to implement this would be to add custom javascript filtering on that particular admin form
Leave for models as it was and try to use inlines in admin page.
So, your admins.py would look something like this:
class SubLocationInline(admin.StackedInline):
model = SubLocation
#admin.register(Location)
class LocationAdmin(admin.ModelAdmin):
.....
inlines = [SubLocationInline]

displaylist of children in parent model one-to-many

I am learning django admin, i have to models with a one-to-many relation between them.
I got something like Manufacturer model where i can add different car manufacturers, and Car model for adding cars. In my django admin page i want to be able to display_list of all cars manfuctred by say manufacturer1 when i click on manufacturer1 entry.
I have found a trick by using Inline model in manufacturer admin model, the problem is that it loads every entry in the database and it takes some time as it's a big table.
Is there any method else to do that or do i have to create a new template ?
EDIT:
The goal is not to load every Car that is FK to Manufacturer1 like with InlineModelAdmin but to get the same display as with display_list with results split in pages
Answer for your updated question:
the way to do it could be by using ProxyModels and overriding ModelAdmin.queryset
You extend the Car model via FordCar, GMCar and use proxy=True in the Meta class, for both those.
Then you can register seperate admins for each of FordCar and GMCar and override the queryset method in each of those ModelAdmin to filter for the respective manufacturer.
Ex:
class FordCarAdmin(admin.ModelAdmin)
list_display = fields = ['name','model','engine']
def queryset(self,request):
qs = super(MyModelAdmin, self).queryset(request)
return qs.filter(manufacturer__name='Ford')
admin.site.register(FordCar,FordCarAdmin)
You have two options.
The easiest approach is to look at the relationship in reverse. Instead of going to a manufacturer change form and seeing all their cars. Go to the cars changelist and filter by manufacturer. You'll have to set the list_filter attribute on the car ModelAdmin to include manufacturer.
Option two, is going to be a huge pain, but you can override change_view on the manufacturer ModelAdmin to add the list of that manufacturer's cars to extra_context. Then, you'll have to override the admin template at 'templates/admin/yourapp/manufacturer/change_form.html'. You can then add to that template to produce the kind of list you're looking for using the list of cars you passed into extra_context, drawing on 'django/contrib/admin/templates/change_list.html' for inspiration.
Give the Django docs on the Admin a good thorough read. There's actually a wealth of info in there.
You don't need any hack. Django admin displays only Cars that have a FK to Manufacturer1, when you select Manufacturer1, as long as you have used the InlineModelAdmin right and as intended.

Formatting inline many-to-many related models presented in django admin

I've got two django models (simplified):
class Product(models.Model):
name = models.TextField()
price = models.IntegerField()
class Invoice(models.Model):
company = models.TextField()
customer = models.TextField()
products = models.ManyToManyField(Product)
I would like to see the relevant products as a nice table (of product fields) in an Invoice page in admin and be able to link to the individual respective Product pages.
My first thought was using the admin's inline - but django used a select box widget per related Product. This isn't linked to the Product pages, and also as I have thousands of products, and each select box independently downloads all the product names, it quickly becomes unreasonably slow.
So I turned to using ModelAdmin.filter_horizontal as suggested here, which used a single instance of a different widget, where you have a list of all Products and another list of related Products and you can add\remove products in the later from the former. This solved the slowness, but it still doesn't show the relevant Product fields, and it ain't linkable.
So, what should I do? tweak views? override ModelForms? I Googled around and couldn't find any example of such code...
Maybe it is not what you expect but I would introduce InvoiceItem model which would link Invoice to Product. So you would have 2x 1:n instead of m:n relation. Then use inline custom form for InvoiceItem and raw_id_fields in that form for Product choice.
In InvoiceItem form then you could add readonly fields that would display values you need to display. You will have to provide data for these fields in Form's init reading them from InvoiceItem instance. Or you could also derive from raw_id_field widget and in render method of this widget append some additional data from the product model?
This is an old question, but I have related to it today.
You can find the answer here - https://blog.ionelmc.ro/2012/01/19/tweaks-for-making-django-admin-faster/
The code:
class MyAdmin(admin.TabularInline):
fields = 'myfield',
def formfield_for_dbfield(self, db_field, **kwargs):
formfield = super(MyAdmin, self).formfield_for_dbfield(db_field, **kwargs)
if db_field.name == 'myfield':
# dirty trick so queryset is evaluated and cached in .choices
formfield.choices = formfield.choices
return formfield
This can cut your waiting times from anything like 5 minutes to around 15 seconds.

Categories

Resources