Main Task:
-
Create Django Admin panel with following list of operations:
- Add a link
- Edit a link
- Delete a link
- Add a source
- Edit a source name
- Add a brand
- Edit a brand name
- Export data to
csv
-
Create API endpoint for export data to
JSONwith 2 optional filters:countryandsource.
- dj-database-url ==
0.5.0 - Django ==
3.2.7 - django-crispy-forms ==
1.12.0 - django-extensions ==
3.1.3 - psycopg2-binary ==
2.9.1 - python-decouple ==
3.4 - whitenoise ==
5.3.0 - django-import-export ==
2.6.0 - gunicorn ==
19.6.0
The main implementation of the first task is on the Products tab in the admin panel, for the Source and Brand fields it was developed only to add new elements and change the current ones (this can be done both on the product page and in place through list_editable).
The Link field can be deleted, modified and new copies added, this can be done on the product page using the buttons next to the field, as in the case of Brand and Source.
The export of the selected data to the CSV was implemented using actions:
def export_as_csv(modeladmin, request, queryset):
meta = modeladmin.model._meta
field_names = [field.name for field in meta.fields]
response = HttpResponse(content_type='text/csv')
response['Content-Disposition'] = 'attachment; filename={}.csv'.format(meta)
writer = csv.writer(response)
writer.writerow(field_names)
for obj in queryset:
writer.writerow([getattr(obj, field) for field in field_names])
return response
export_as_csv.short_description = "Export Selected as CSV"Also, the admin panel has the ability to filter values by Country, Brand and/or Category (list_filter).
To expand the functionality, the django-import-export library was involved, with the help of which the export and import of files in such formats as csv, xls, xlsx, tsv, ods, json, yaml and html was implemented. To take advantage of this, there are buttons in the upper right corner of the Products admin page.
To integrate django-import-export with our Product model, we will create a ProductResource class in admin.py that will describe how this resource can be imported or exported:
class ProductResource(resources.ModelResource):
# we need this five fields to display the actual values that are hidden behind ForeignKeys
source = fields.Field(column_name='source', attribute='source',
widget=ForeignKeyWidget(Source, 'source'))
country = fields.Field(column_name='country', attribute='country',
widget=ForeignKeyWidget(Country, 'country'))
brand = fields.Field(column_name='brand', attribute='brand',
widget=ForeignKeyWidget(Brand, 'brand'))
category = fields.Field(column_name='category', attribute='category',
widget=ForeignKeyWidget(Category, 'category'))
link = fields.Field(column_name='link', attribute='link',
widget=ForeignKeyWidget(Link, 'link'))
class Meta:
model = Product
fields = ('source', 'country', 'brand', 'category', 'link') # fields to export
import_id_fields = ['source', 'country', 'brand', 'category', 'link'] # fields to import Admin integration is achieved by subclassing ImportExportModelAdmin:
@admin.register(Product)
class ProductAdmin(ImportExportModelAdmin):
...
resource_class = ProductResource| Admin Panel (Products) | Admin Panel (Product Page) | Add Source | Edit Brand |
|---|---|---|---|
![]() |
![]() |
![]() |
![]() |
| Delete Link | Export Page | Export Result (JSON) | Export CSV |
|---|---|---|---|
![]() |
![]() |
![]() |
![]() |
| Export Result (CSV) | Import Page | Import Result |
|---|---|---|
![]() |
![]() |
![]() |
The implementation of this part is in folder api/ and accordingly on url ../api/v1/get/ and ../api/v1/post/.
../api/v1/post/ - deals with the creation of new instances of the Product, as well as the validation of parameters (validation of the URL and the country).
../api/v1/get/- returns a JSON file with Product objects and has 2 additional filters: country and source.
For the convenience of filling in the data for POST I leave the form, but it is easy to change.
| Form Example | Parameters Validation (Error) | Parameters Validation (Success) |
|---|---|---|
![]() |
![]() |
![]() |
| JSON Response (Postman) | JSON Response - Filter by Source (Postman) | JSON Response - Filter by Country (Postman) |
|---|---|---|
![]() |
![]() |
![]() |
populate_db.py script was used to fill the database with data from ProductLink.csv
python manage.py runscript populate_db
















