Browse Source

Added user account creation, refactored most views, still some CSS to write

master
Phuntsok Drak-pa 1 year ago
parent
commit
a41cd9a120
No known key found for this signature in database GPG Key ID: 9CB34B6827C66D22
7 changed files with 249 additions and 81 deletions
  1. +19
    -2
      dictionary/forms.py
  2. +27
    -14
      dictionary/models.py
  3. +5
    -0
      dictionary/templates/dictionary/form_template.html
  4. +1
    -0
      dictionary/templates/dictionary/index.html
  5. +29
    -0
      dictionary/templates/dictionary/registration_form.html
  6. +12
    -7
      dictionary/urls.py
  7. +156
    -58
      dictionary/views.py

+ 19
- 2
dictionary/forms.py View File

@@ -1,9 +1,26 @@
"""
Forms that will be used for various user actions, such as language selection on
the main page, user registration or authentification.
"""
from django import forms
from django.contrib.auth.models import User
from .models import Language


class SelectLangForm(forms.Form):
natlang = forms.ModelChoiceField(
queryset=Language.objects.all(), label="Natural Language:", to_field_name="code")
queryset=Language.objects.all(),
label="Natural Language:",
to_field_name="code")
conlang = forms.ModelChoiceField(
queryset=Language.objects.all(), label="Constructed Language:", to_field_name="code")
queryset=Language.objects.all(),
label="Constructed Language:",
to_field_name="code")


class UserForm(forms.ModelForm):
password = forms.CharField(widget=forms.PasswordInput)

class Meta:
model = User
fields = ['username', 'email', 'password']

+ 27
- 14
dictionary/models.py View File

@@ -8,7 +8,9 @@ from django.utils.text import slugify


class Language(models.Model):
"""A general class to refer to languages, with its code and its name"""
"""
A general class to refer to languages, with its code and its name
"""
code = models.CharField(max_length=4, primary_key=True)
name = models.CharField(max_length=128)
conlang = models.BooleanField(default=True)
@@ -17,13 +19,17 @@ class Language(models.Model):
return "{0.name} ({0.code})".format(self)

class Meta:
"""Meta sub-class for ordering the languages"""
"""
Meta sub-class for ordering the languages
"""
ordering = ('code', )


class Gender(models.Model):
"""Contains all possible gender in the languages supported by the
dictionary, be it from natlangs or conlangs"""
"""
Contains all possible gender in the languages supported by the
dictionary, be it from natlangs or conlangs
"""
code = models.CharField(max_length=4, primary_key=True)
name = models.CharField(max_length=128)

@@ -31,7 +37,9 @@ class Gender(models.Model):
return "{0.name} ({0.code})".format(self)

class Meta:
"""Meta sub-class for ordering the genders"""
"""
Meta sub-class for ordering the genders
"""
ordering = ('name', )


@@ -44,18 +52,20 @@ class Wordclass(models.Model):
return "{0.name} ({0.code})".format(self)

class Meta:
"""Meta sub-class for ordering the word classes"""
"""
Meta sub-class for ordering the word classes
"""
ordering = ('code', )


class Word(models.Model):
"""Represents any word from any language. It has a self-representation with
\"word\", a reference to which language it belongs to with \"language\",
a list of words \"translation\" that can be its translation (duh), a
reference to its gender with \"gender\" (duh2), its word class with
\"wordclass\", some \"details\" about the word (no more than 5000 chars),
its \"etymology\" (no more than 5000 chars) and a list of words that can be
its etymological \"roots\"
"""
Represents any word from any language. It has a self-representation with
"word", a reference to which language it belongs to with "language", a list
of words "translation" that can be its translation (duh), a reference to its
gender with "gender" (duh2), its word class with "wordclass", some "details"
about the word (no more than 5000 chars), its "etymology" (no more than 5000
chars) and a list of words that can be its etymological "roots"
"""
word = models.CharField(max_length=128)
slug = models.CharField(max_length=128)
@@ -77,4 +87,7 @@ class Word(models.Model):
super(Word, self).save(args, kwargs)

class Meta:
ordering = ('word', )
"""
Meta sub-class for ordering words
"""
ordering = ('slug', )

+ 5
- 0
dictionary/templates/dictionary/form_template.html View File

@@ -0,0 +1,5 @@
{% for field in form %}
<span class="text-danger small">{{field.errors}}</span>
<label class="control-lablel">{{field.label_tag}}</label>
<div>{{field}}</div>
{% endfor %}

+ 1
- 0
dictionary/templates/dictionary/index.html View File

@@ -55,6 +55,7 @@
</destlang>
<submit class="form-style">
<input type="submit" value="Let’s Go!">
</submit>
</div>
</form>
{% endblock %}

+ 29
- 0
dictionary/templates/dictionary/registration_form.html View File

@@ -0,0 +1,29 @@
{% extends 'dictionary/base.html' %}
{% load staticfiles %}

<!---------------------------------------------------------------------------->
<!-- Registration page -->
<!---------------------------------------------------------------------------->


<!-- title ------------------------------------------------------------------->
{% block title %}Account Registration{% endblock %}

<!-- headers ----------------------------------------------------------------->
{% block addhead %}
<link rel="stylesheet" href="{% static 'dictionary/registration.css' %}" type="text/css" media="screen" />
{% endblock %}

<!-- sidebar ----------------------------------------------------------------->
{% block sidebarcontent %}
{% endblock %}

<!-- body -------------------------------------------------------------------->
{% block body %}
<h3>Register a new account</h3>
<form method="post" action="">
{% csrf_token %}
{% include 'dictionary/form_template.html' %}
<button type="submit">Submit</button>
</form>
{% endblock %}

+ 12
- 7
dictionary/urls.py View File

@@ -8,29 +8,28 @@ urlpatterns = [

# choix du langage traduit et du langage de traduction
# /dictionary/
# url(r'^$', views.index, name='index'),
path('', views.index, name='index'),
path('', views.IndexView.as_view(), name='index'),

# renvoie à la liste des mots de la première initiale de <from_lang>
# /search/<from_lang>/<to_lang>/
# /search/HJP/FRA
url(r'^search/(?P<natlang>\w+)/(?P<conlang>\w+)/*$',
views.index_lang,
views.WordListView.as_view(),
name='index_lang'),

# renvoie à la liste des mots de la première initiale de <from_lang>
# /search/<from_lang>/<to_lang>/<initial>
# /search/HJP/FRA/a
url(r'^search/(?P<natlang>\w+)/(?P<conlang>\w+)/(?P<initial>\w)/*$',
views.list_initial,
views.InitialsListView.as_view(),
name='index_initial'),

# renvoie le détail de la traduction de `word` en `from_lang` vers
# `to_lang`
# /word/<from_lang>/<to_lang>/<word>/
# /word/<from_lang>/<to_lang>/<slug>/
# /word/HJP/FRA/hj-lp
url(r'^word/(?P<from_lang>\w+)/(?P<to_lang>\w+)/(?P<word>[-\w0-9]+)/*$',
views.details,
url(r'^word/(?P<from_lang>\w+)/(?P<to_lang>\w+)/(?P<slug>[-\w0-9]+)/*$',
views.DetailView.as_view(),
name='details'),

# renvoie cinq mots de `from_lang` commençant par `word`
@@ -39,4 +38,10 @@ urlpatterns = [
url(r'^guess/(?P<from_lang>\w+)/(?P<word>[-\w0-9]+)/*$',
views.guessword,
name='guessword'),

# user account registration page
path('register', views.UserFormView.as_view(), name='register'),

# user logout
path('logout', views.logout_view, name='logout'),
]

+ 156
- 58
dictionary/views.py View File

@@ -2,93 +2,146 @@
Views for the dictionary
"""

from django.shortcuts import render, get_object_or_404
from django.http import HttpResponseRedirect
from django.contrib.auth import authenticate, login, logout
from django.shortcuts import render, redirect
from django.views.generic import View, DetailView, ListView
# from django.views.generic.edit import CreateView, UpdateView, DeleteView
from .forms import SelectLangForm, UserForm
from .models import Language, Word
from .forms import SelectLangForm


def index(request):
class IndexView(View):
"""
Will display the list of languages available and let the user choose which
language to get the words from and to which language it will be translated.
The two languages cannot be two natural languages or two conlangs.
View for the main page. Two drop-down boxes will give the choice between
which languages to translate, one will be used to select a natural language,
the other a conlang.

View for https://dict.phundrak.fr/
View for /
"""
form_class = SelectLangForm
template_name = 'dictionary/index.html'
error_message = ""
if request.method == 'POST':
form = SelectLangForm(request.POST)

def get(self, request):
"""
Displays the index page
"""
form = self.form_class(None)
return render(
request, self.template_name, {
'form': form,
'conlangs': Language.objects.filter(conlang=True),
'natlangs': Language.objects.filter(conlang=False),
'error_message': self.error_message
})

def post(self, request):
"""
Processes the form and redirects to the correct bilingual word list page
if the form is correct, or to the main page if not
"""
form = self.form_class(request.POST)
if form.is_valid():
natlang = form.cleaned_data['natlang']
conlang = form.cleaned_data['conlang']
return HttpResponseRedirect('/search/' + natlang.code + '/' +
conlang.code)
print(form.errors)
error_message = form.errors
else:
form = SelectLangForm()
# all_languages = Language.objects.all()
conlangs = Language.objects.filter(conlang=True)
natlangs = Language.objects.filter(conlang=False)
return render(request, 'dictionary/index.html', {
'conlangs': conlangs,
'natlangs': natlangs,
'error_message': error_message
self.error_message = form.errors
return render(
request, self.template_name, {
'form': form,
'conlangs': Language.objects.filter(conlang=True),
'natlangs': Language.objects.filter(conlang=False),
'error_message': self.error_message,
})


def index_lang(request, natlang, conlang):
class WordListView(ListView):
"""
Will list all the words from the language `natlang` translated to the
language `conlang` and vice-versa

View for https://dict.phundrak.fr/search/from_lang/to_lang
View for /search/from_lang/to_lang
"""
natwords = Word.objects.filter(language__code=natlang)
conwords = Word.objects.filter(language__code=conlang)
natlang = Language.objects.get(code=natlang)
conlang = Language.objects.get(code=conlang)
return render(
request, 'dictionary/language.html', {
'natwords': natwords,
'conwords': conwords,
'natlang': natlang,
'conlang': conlang,
})
template_name = 'dictionary/language.html'
context_object_name = 'natwords'

def get_queryset(self):
"""
Get initial values to display
"""
return Word.objects.filter(
language__code=self.kwargs['natlang'],
translation__language__code=self.kwargs['conlang'])

def list_initial(request, from_lang, to_lang, initial):
def get_context_data(self, **kwargs):
"""
Get some additional values
"""
This will list all the words from the language `from_lang` beginning with
the letter `initial` and translated to the language `to_lang`. It is similar
to `index_lang` but restricts the amount of words displayed on a single
page.
context = super(WordListView, self).get_context_data(**kwargs)
context['conwords'] = Word.objects.filter(
language__code=self.kwargs['conlang'],
translation__language__code=self.kwargs['natlang'])
context['natlang'] = Language.objects.get(code=self.kwargs['natlang'])
context['conlang'] = Language.objects.get(code=self.kwargs['conlang'])
return context


View for https://dict.phundrak.fr/search/from_lang/to_lang/initial
class InitialsListView(ListView):
"""
pass
Displays all the words from both languages beginning with a specified
initial letter
"""

# TODO: create dedicated template
template_name = 'dictionary/language.html'
context_object_name = 'natwords'

def get_queryset(self):
"""
Get initial values to display
"""
return Word.objects.filter(
language__code=self.kwargs['natlang'],
slug__startswith=self.kwargs['initial'],
translation__language__code=self.kwargs['conlang'])

def get_context_data(self, **kwargs):
"""
Get some additional values
"""
context = super(InitialsListView, self).get_context_data(**kwargs)
context['conwords'] = Word.objects.filter(
language__code=self.kwargs['conlang'],
slug__startswith=self.kwargs['initial'],
translation__language__code=self.kwargs['natlang'])
context['natlang'] = Language.objects.get(code=self.kwargs['natlang'])
context['conlang'] = Language.objects.get(code=self.kwargs['conlang'])
return context

def details(request, from_lang, to_lang, word):

class DetailView(DetailView):
"""
Displays the details about the word `word` from the language `from_lang` if
this word is from a conlang and will display its translations to the
language `to_lang`

View for https://dict.phundrak.fr/word/from_lang/to_lang/word
View for /word/from_lang/to_lang/slug
"""
from_lang = Language.objects.get(code=from_lang)
to_lang = Language.objects.get(code=to_lang)
word = get_object_or_404(Word, language=from_lang, slug=word)
translations = word.translation.filter(language=to_lang)
return render(
request, 'dictionary/details.html', {
'word': word,
'translations': translations,
'from_lang': from_lang,
'to_lang': to_lang,
})
model = Word
template_name = 'dictionary/details.html'
context_object_name = 'word'

def get_context_data(self, **kwargs):
context = super(DetailView, self).get_context_data(**kwargs)
context['translations'] = context['word'].translation.filter(
language=self.kwargs['to_lang'])
context['from_lang'] = Language.objects.get(
code=self.kwargs['from_lang'])
context['to_lang'] = Language.objects.get(code=self.kwargs['to_lang'])
return context


def guessword(request, from_lang, word):
@@ -96,7 +149,7 @@ def guessword(request, from_lang, word):
Is used to get five words from `from_lang` beginning with `word`. This will
be used for word suggestion when using the search bar.

View for https://dict.phundrak.fr/guess/from_lang/word
View for /guess/from_lang/word
"""
pass

@@ -105,7 +158,7 @@ def user_add_word(request, language):
"""
Allows authorized users to add new words to a selected language

View for https://dict.phundrak.fr/addword/language/
View for /addword/language/
"""
pass

@@ -114,7 +167,7 @@ def user_add_language(request):
"""
Allows authorized users to add new languages

View for https://dict.phundrak.fr/addlanguage/
View for /addlang/
"""
pass

@@ -123,7 +176,7 @@ def user_add_word_class(request):
"""
Allows authorized users to add new word classes

View for https://dict.phundrak.fr/addwclass
View for /addwclass
"""
pass

@@ -132,7 +185,7 @@ def user_add_gender(request):
"""
Allowsauthorized users to add new genders

View for https://dict.phundrak.fr/addgender
View for /addgender
"""
pass

@@ -141,6 +194,51 @@ def user_edit_word(request, language, word):
"""
Allows authorized users to edit existing `word` in selected `language`

View for https://dict.phundrak.fr/edit/language/word
View for /edit/language/word
"""
pass


class UserFormView(View):
"""
View to proceed to user account creation

View for /register
"""
form_class = UserForm
template_name = 'dictionary/registration_form.html'

# display blank form
def get(self, request):
form = self.form_class(None)
return render(request, self.template_name, {'form': form})

# Process form data
def post(self, request):
form = self.form_class(request.POST)
if form.is_valid():
user = form.save(commit=False)

# cleaned (normalized) data
username = form.cleaned_data['username']
password = form.cleaned_data['password']
user.set_password(password)
user.save()

# returns User objects if credentials are correct
user = authenticate(username=username, password=password)
if user is not None and user.is_active:
login(request, user)
# request user.username
return redirect('dictionary:index')
return render(request, self.template_name, {'form': form})


def logout_view(request):
"""
View to allow logged in users to log out.

View for /logout
"""
logout(request)
return redirect('dictionary:index')