Create django webapp + REST API endpoints - django

I'm trying to create a website with a mobile application. I worked with web apps and REST apis separately but with this project I have to combine both.
My question is how do I have to combined this two sides of the projects.
Suposse I have a User model which has Tasks. Currently I have those models in an app called, for example, myRESTapp. But now, I want to be able to edit the tasks and take advantage of Django forms, but I'm not to do another application called webapp and implement forms based on models that are inmyRESTapi. I think it would not be a good practice considering the modularity of applications.

You can have multiple apps in one Django project. I usually have one main app that contains the main models and additional apps build on it.
Also, if you want to use apps in different projects, just make them reusable and put them into separate repositories (which you could add as requirements and install with pip).
As for a REST API, check out the great Django Rest Framework. It provides full CRUD functionality and in combination with crispy forms you can even add/modify data with a simple web UI.
An example of how I structured one of my projects:
base # basic application
├── __init__.py
├── admin
│ ├── __init__.py
├── ├── filters.py # custom filters for the Django Admin
│ └── models.py # enhancements for the Django Admin
├── apps.py
├── db_router.py # database router to distinguish between default and legacy DB
├── migrations # DB migrations (default & legacy)
├── models
│ ├── __init__.py
│ └── default.py # default models
│ └── legacy.py # legacy models
├── services
│ ├── __init__.py
│ ├── service1.py
│ ├── service2.py
├── tests.py
manage.py
my_api_app
├── __init__.py
├── apps.py
├── serializers.py # DRF Serializers
├── services.py # specific services for this app
├── tests.py
├── urls.py # API URLs
├── views.py # DRF ViewSets
my_web_app
├── __init__.py
├── apps.py
├── services.py # specific services for this app
├── static
├── ├── css
├── ├── img
├── ├── js
├── templates
├── tests.py
├── urls.py # website URLs
├── views.py # web views
projectname
├── __init__.py
├── settings
├── ├── __init__.py
│ ├── base.py # base settings for all environments
│ ├── dev.py # local dev settings (DEBUG, etc)
│ ├── prod.py # production settings (default)
│ └── test.py # test settings (sqlite DBs for testing)
├── urls.py # urlpatterns (API, website & admin)
├── wsgi.py
requirements
├── base.txt # requirements for all environments
├── dev.txt # local dev requirements
├── optional.txt # optional requirements for HTML doc creation
├── prod.txt # production requirements
└── test.txt # test env requirements
requirements.txt # default requirements (prod)
scripts
├── post-merge.sh # githook for deployment on server
├── doc.sh # create the code doc
├── coverage.sh # create the code doc
So I have my base app, that contains the models and everything that's used in both of the other apps and an app for the API and one for the website.
I come from PHP and Symfony, where I really fell in love with the idea of reusable services. That's how I keep logic out of my views and keep closer to an actual MVC (which is something Django isn't)

Related

Django: collectstatic does not collect my app

I am going to deploy on IIS so all the following commands were executed on Windows (Server2016)
This is the structure of my django project:
$ C:\inetpub\wwwroot\djangoProject
.
├── static
├── manage.py
├── websrv
├── __init__.py
├── admin.py
├── apps.py
├── models.py
├── tests.py
├── urls.py
└── views.py
└── djangoProject
├── __init__.py
├── settings.py
├── urls.py
└── wsgi.p
I set STATIC_ROOT in C:\inetpub\wwwroot\djangoProject\djangoProject\settings.py to:
STATIC_ROOT = 'C:/inetpub/wwwroot/djangoProject/static'
and obviously my app name (websrv) was added to the INSTALLED_APPS in settings.py too.
but when I run python manage.py collectstatic, the result is that only admin folder is collected under C:\inetpub\wwwroot\Alsatex\static and there is no folder for my main app (websrv)

Django dev server not recognizing new files after directory modification

I have a Django project with 2 apps and was writing some functions in a utils.py file in one of the apps. I wanted to break this up into two separate files in their own subdirectory so I created a new directory 'utils' a level below the app directory and placed the two utils1.py and utils2.py files in there.
I had some issues with importing something from the other app so I ended up scrapping this idea and moving everything back into one file in the base directory of the original app, exactly like it was before. Now when I runserver it is not picking up any new files that are created within apps. Not just the ones that I recreated but any new files. Files that were created prior to the change are running just fine.
So, in summary new utils.py files that I recreated in the app directory are not running when the dev server is started, and when I try to run one of them manually they run like any other python file, but imports from other locations in the project are not being recognized.
No other changes were made and new files were running perfectly fine before the directory changes.
After the changes:
├── app1
│   ├── __init__.py
│   ├── admin.py
│   ├── apps.py
│   ├── migrations
│   ├── models.py
│   ├── permissions.py
│   ├── serializers.py
│   ├── tests.py
│   ├── urls.py
│   ├── utils.py
│   └── views.py
├── manage.py
├── project
│   ├── __init__.py
│   ├── settings.py
│   ├── urls.py
│   └── wsgi.py
└── app2
├── __init__.py
├── admin.py
├── apps.py
├── utilities <--- added
├── util1.py
└── util2.py
├── migrations
├── models.py
├── serializers.py
├── tests.py
├── urls.py
└── views.py
After reverting back to previous structure (not working):
├── app1 <--- new files created here aren't running
│   ├── __init__.py
│   ├── admin.py
│   ├── apps.py
│   ├── migrations
│   ├── models.py
│   ├── permissions.py
│   ├── serializers.py
│   ├── tests.py
│   ├── urls.py
│   ├── utils.py
│   └── views.py
├── manage.py
├── project
│   ├── __init__.py
│   ├── settings.py
│   ├── urls.py
│   └── wsgi.py
└── app2 <--- new files created here aren't running
├── __init__.py
├── admin.py
├── apps.py
├── util1.py <--- moved back into app directory
├── migrations
├── models.py
├── util2.py <--- moved back into app directory
├── serializers.py
├── tests.py
├── urls.py
└── views.py
I've tried clearing the pycache files, restarting the dev server, restarting terminal, etc. to no avail.
I figured out what was going on. My assumption was that any new python files in an installed app would be automatically run, but something from the file needs to be imported first from somewhere else in the project. Before the changes I had an import in the utils.py file so the dev server was running it, but after the changes there were no imports from elsewhere in the project. Issue is fixed and working now.

DJANGO 1.11 - Can't find fixtures

Problem
I was trying to use fixtures to populate my database, so I started by reading through the documentation for loaddata and by default, it looks in the fixtures directory inside each app for fixtures. My problem is that when I run python manage.py loaddata I'm getting an error, but when I give it the path for teams.yaml it works fine. Do I need to setup something for it to work?
Documentation
https://docs.djangoproject.com/en/1.11/howto/initial-data/#where-django-finds-fixture-files
Error
usage: manage.py loaddata [-h] [--version] [-v {0,1,2,3}]
[--settings SETTINGS] [--pythonpath PYTHONPATH]
[--traceback] [--no-color] [--database DATABASE]
[--app APP_LABEL] [--ignorenonexistent] [-e EXCLUDE]
fixture [fixture ...]
manage.py loaddata: error: No database fixture specified. Please provide the path of at least one fixture in the command line.
Team App Dir
team
├── admin.py
├── apps.py
├── fixtures
│   └── teams.yaml
├── __init__.py
├── migrations
│   ├── 0001_initial.py
│   ├── 0002_auto_20190204_0438.py
│   ├── 0003_remove_team_team_name.py
│   ├── `enter code here`0004_team_team_name.py
│   ├── __init__.py
│   └── __pycache__
│   ├── 0001_initial.cpython-36.pyc
│   ├── 0002_auto_20190204_0438.cpython-36.pyc
│   ├── 0003_remove_team_team_name.cpython-36.pyc
│   ├── 0004_team_team_name.cpython-36.pyc
│   └── __init__.cpython-36.pyc
├── models.py
├── __pycache__
│   ├── admin.cpython-36.pyc
│   ├── apps.cpython-36.pyc
│   ├── __init__.cpython-36.pyc
│   └── models.cpython-36.pyc
├── tests.py
└── views.py
Model
from django.db import models
class Team(models.Model):
team_name = models.CharField(max_length=32)
team_description = models.TextField(max_length=512, blank=False)
class Meta:
permissions = (
('create_team', 'Can create a team'),
)
Fixture (teams.yaml)
- model: team.Team
pk: 1
fields:
team_name: team_name_example
team_descrition: team_description_example
Should you define FIXTURE_DIRS in your settings file so django find your fixtures which there are there.
settings.py
FIXTURE_DIRS = [
os.path.join(BASE_DIR, 'fixtures')
]
# statements
Reference
The error says:
No database fixture specified. Please provide the path of at least one fixture in the command line.
You need to provide a fixturename in loaddata command, in your case:
python manage.py loaddata team
It was specified in the doc that by default Django will look into fixtures directory inside your app with the specified fixturename. Also the command accepts ./path/to/fixtures/ which overrides the searching of fixtures directory.

Where should I place the login and logout in Django?

I am beginner at Django. I was wondering what is the best practice to place the user login and logout functions. I already have a global static folder and templates.
Should I create a view.py under my Project-Root folder for the functions? Or should I create a separate APP just to put this functions in?
I already have this functions and templates inside myapp view.py
projectname]/ <- project root
├── [projectname]/ <- Django root
│ ├── __init__.py
│ ├── settings/
│ ├── urls.py
│ └── wsgi.py
├── myapp/
│ ├─ __init__.py
│ └── view.py
│
├── manage.py
│
├── static/
│ └── GLOBAL STATIC FILES
└── templates/
└── GLOBAL TEMPLATES
You should use some user authentication within one App which you have created, or create one App just for managing accounts.
Since you are a beginner you should take a look at Django-admin user authentication.
https://docs.djangoproject.com/en/1.10/topics/auth/
The answer to the question is quite subjective i.e. varies from project to project, or developer to developer. My suggestions 'd be:
As you have asked for the log-in and log-out functions, this means you'll be handling users for your app - so a good approach 'd be to have a users app, and place the functions in users/views.py
For complex system - where you may have different types of users i.e. users, admin_users, partners, etc. You can have separate directory at project root e.g. lib/ and have functions.py in it, keep all the project wide usable functions, utilities in this file.
projectname]/ <- project root
├── [projectname]/ <- Django root
│ ├── __init__.py
│ ├── settings/
│ ├── urls.py
│ └── wsgi.py
├── myapp/
│ ├─ __init__.py
│ └── view.py
│
├── lib/
│ ├─ __init__.py
│ └── functions.py
│
├── manage.py
│
├── static/
│ └── GLOBAL STATIC FILES
└── templates/
└── GLOBAL TEMPLATES
Your question is not clear as to what you want to place. Is the template files you want to place in or the view function "logout" and "login"? I assume it has to be the "login" and "logout" function what you are looking for.
You have to create a views.py file under "[projectname]/apps" folder.
view for login
def login_validate(request):
if request.method == "POST":
username = request.POST['username']
password = request.POST['password']
user = authenticate(username= username, password= password)
if user is not None:
login(request,user)
return HttpResponseRedirect('/--template name--/')
else:
return HttpResponseRedirect('/--template name--/')
else:
return HttpResponseRedirect('/--template name--/')
view for logout
def logout_page(request):
logout(request)
return render(request,"logout_page.html",{})
Above are the functions. You will have to add few things in settings.py before doing this.
And also create a urls.py file under apps folder and link it to main urls.py file.
I hope this is clear.
https://docs.djangoproject.com/en/1.10/topics/auth/default/
https://www.youtube.com/watch?v=eMGtdtNR4es
The above links are helpful.

Sphinx documentation inside a Flask running web application

I've locally built static Sphinx documentations (using make html).
I wish now to integrate the Sphinx files into my webapp that runs with Flask. From the Flask running application, I simply mean to include an hyperlink towards the Sphinx documentation, that will serve as help for the application.
Websupport seems the way to follow, but it's not clear to me how I should bridge the Flask framework to the Sphinx files.
Thanks for any help,
Regards
Other solutions nicely omit the Flask object initialization, which lead me to bang my head against the wall for a while.
Without touching the Sphinx project structure at all, here's the solution that worked for me:
from flask import Flask
app = Flask(__name__, static_url_path='/', static_folder='_build/html/')
#app.route('/')
#app.route('/<path:path>')
def serve_sphinx_docs(path='index.html'):
return app.send_static_file(path)
if __name__ == '__main__':
app.run(debug=True)
And below is the file structure of the project, where <doc> represents the rst files I actually wrote for the documentation, and app.py is the file containing the Flask app code above.
.
├── Makefile
├── _build
│   ├── doctrees
│   │   ├── index.doctree
│   │   ├── <doc>.doctree
│   │   ├── ...
│   │   └── <doc>.doctree
│   └── html
│   ├── _images
│   ├── _modules
│   │   ├── index.html
│   │   └── <package name>
│   │   └── ...
│   ├── _sources
│   │   ├── <doc>.rst.txt
│   │   ├── ...
│   │   └── <doc>.rst.txt
│   ├── _static
│   │   ├── ajax-loader.gif
│   │   ├── alabaster.css
│   │   └── ...
│   ├── genindex.html
│   ├── index.html
│   ├── objects.inv
│   ├── py-modindex.html
│   ├── search.html
│   ├── searchindex.js
│   ├── <doc>.html
│   ├── ...
│   └── <doc>.html
├── _static
│   ├── custom.css
│   └── <myimage>.gif
├── _templates
├── app.py
├── conf.py
├── index.rst
├── make.bat
├── <doc>.rst
├── ...
└── <doc>.rst
You could just handle it with your web server, the same way you handle the /static directory in Flask. For example if you used Apache as your production web server, you might add
Alias /documentation /location/of/sphinx/html
<Directory /location/of/sphinx/html>
Order deny,allow
Allow from all
</Directory>
to your Apache site configuration, so then you could just link directly to http://yoursite.com/documentation to access the Sphinx files, avoiding Flask altogether.
You can copy the _build/html folder from your docs to a doc folder in your flask static directory, and serve them with the following rule:
#app.route('/doc/<dir>/<filename>', defaults={'static': True})
def doc(dir='',filename='index.html'):
path = join(dir,filename)
return app.send_static_file(path)
In some cases you do not want to expose your docs to all users so configuring at the Apache or Nginx level is not an option. The following worked for me:
#app.route('/docs', defaults = {'filename': 'index.html'})
#app.route('/docs/<path:filename>')
#login_required
def web_docs(filename):
path = os.path.join('docs/html', filename)
return app.send_static_file(path)
As far as I've seen the Flask.send_static_file method requires that the file resides within the static directory. Sub directories are not supported using this method.
To serve a file from any location use the Flask.send_from_directory method.
Example:
import flask
from flask import send_from_directory
app = Flask(
import_name=__name__
)
#app.route('/docs/', defaults={'filename': 'index.html'})
#app.route('/docs/<path:filename>')
def docs(filename) -> flask.send_from_directory:
docs_dir = os.path.join(os.path.dirname(__file__), 'docs', 'build', 'html')
return send_from_directory(directory=docs_dir, path=filename)
The example assumes docs\build\html\ exists in the same directory as the python file. Change docs_dir as needed.
Additionally, without appending a trailing backslash to the default route, the page did not render properly, therefore I changed the default route to /docs/.
Set the BUILDDIR path in sphinx Makefile
BUILDDIR = app/static/docs
add flask routes
#app.get('/docs/')
#app.get('/docs/<path:filename>')
def get_docs(filename='index.html'):
path = os.path.join('docs/html', filename)
return app.send_static_file(path)
Build the sphinx documentation.
$ make html
You can browse to http://127.0.0.1:5000/docs for sphinx documentation page. All the sphinx docs static files will be served under this route. You can also add Flask Authentication to the route if needed.
Test Versions:
Flask: 2.0.2
Sphinx: 4.3.1