Django redirect if User has created object - django

in my model the USER will create the object startup_name, however, i want to carry out a check when user click the button again that of he has created the object so he will be redirected to another page.
class Startup ( models.Model ) :
author = models.OneToOneField ( User , on_delete = models.CASCADE )
startup_name = models.CharField ( 'Startup Name' , max_length = 32 , null = False , blank = False )
class startupform(forms.ModelForm):
class Meta:
model = Startup
fields = ('startup_name',)
widgets = {
'startup_name': forms.TextInput(attrs = {'class':'form-control'}),
}
def clean(self):
super ( ).clean ( )
startup_name = self.cleaned_data.get ( 'startup_name' )
startup_qs = Startup.objects.filter ( startup_name = startup_name )
if startup_qs.exists ( ):
raise forms.ValidationError ( 'This Startup Already Exist!' )
#login_required
def create_startupform(request) :
q = Startup.objects.all()
if q.exists():
return redirect ( 'str_detailedview' )
else:
form = startupform ( request.POST or None )
if form.is_valid ( ) :
instance = form.save (commit = False)
instance.author = request.user
instance.save()
return redirect ( 'str_detailedview' )
else:
form = startupform()
return render ( request , 'str_name.html' , { 'form' : form } )

you need check input name into Startup model and if its exist then you can redirect:
#login_required
def create_startupform(request) :
if request.method == 'POST' :
form = startupform ( request.POST )
if form.is_valid ( ) :
startup_name_input = request.POST.get('startup_name')
if Startup.objects.filter(startup_name='startup_name_input').exists():
return render(request, 'some_template.html', {'form' : form})
result = form.save ( commit = False )
result.author = request.user
result.save ( )
return redirect ( 'test', startup_id = result.pk)
else :
form = startupform ( )
return render ( request , 'str_name.html' , { 'form' : form } )

Related

Properly configure TrigramSimilarity and SearchVector for searching users

I have written a search function in order to do FTS on my user model however, I am having a hard time figuring out how to configure it in order to get similar results as well, for instance, if the username contains MOST character of the search query it should display it as well. for instance if I search for bob and there is a user with username bobuser13 it should be displayed as well.
Currently, my search function is:
def search(self, search_text):
search_vectors = (
SearchVector(
'username', weight='A', config='english'
) + SearchVector(
'last_name' , weight='B', config='english'
) + SearchVector(
'first_name' , weight='C', config='english'
)+ SearchVector(
'first_name','last_name', weight='D', config='english'
) + + SearchVector(
'bio', weight='D', config='english'
)
)
search_query = SearchQuery(
search_text, config=' english'
)
search_rank = SearchRank(search_vectors,search_query)
trigram = TrigramSimilarity(
'username', search_text
) + TrigramSimilarity(
'last_name',search_text
) + TrigramSimilarity(
'first_name',search_text
)
qs = (
self.get_queryset()
.filter(sv=search_query)
.annotate(rank=search_rank, trigram=trigram, bs=Greatest('rank','trigram'))
.filter(Q(bs__gte=0.1))
.order_by('-bs')
)
return qs
And my user model is:
class Profile(AbstractUser):
bio = models.TextField()
sv = pg_search.SearchVectorField(null=True)
objects = ProfileManager()
class Meta:
indexes = [
GinIndex(fields=['sv'],name='search_idx_user'),
]
def __str__(self):
return self.username
def get_absolute_url(self):
return "{}".format(self.slug)
how can I configure this so that it also includes similar names as well?

DJANGO <OPTION> element with EXTRA ATTRIBUTES

How can we add some extra tags to DJANGO FORM MODEL tag element? I all-read tried change something inside form.py/class META/widgets but without nothing.
class MySelect( forms.Select ):
def __init__( self, attrs = None, choices = (), option_xtra_attr = '' ):
self.option_xtra_attr = option_xtra_attr
super( MySelect, self ).__init__( attrs, choices )
def render_option( self, selected_choices, option_value, option_label, option_xtra_attr = '' ):
if option_value is None:
option_value = ''
option_value = force_text( option_value )
if option_value in selected_choices:
selected_html = mark_safe( ' selected="selected"' )
if not self.allow_multiple_selected:
# Only allow for a single selection.
selected_choices.remove( option_value )
else:
selected_html = ''
return format_html( '<option value="{}"{}{}>{}</option>',
option_value,
selected_html,
option_xtra_attr,
force_text( option_label ) )
class MonitoringSpot_InLine_FORM( forms.ModelForm ):
class Meta:
model = MonitoringSpotClass
fields = [ 'monitoringSpot_NODE_monitoringAreaType', ]
widgets = {
'monitoringSpot_NODE_monitoringAreaType': MySelect( option_xtra_attr = { 'xdata': 'value' } )
}
It's works better
class OptionAttr( forms.Select ):
def __init__( self, *args, **kwargs ):
self.src = kwargs.pop( 'attributes', { } )
super().__init__( *args, **kwargs )
def create_option( self, name, value, label, selected, index, subindex = None, attrs = None ):
splitedLabel = label.split(",")
options = super( OptionAttr, self ).create_option( name, value, label, selected, index, subindex = None, attrs = None )
for k, v in self.src.items():
if v != True:
options[ 'attrs' ][ k ] = v
else:
options[ 'attrs' ][ k ] = splitedLabel[1:]; options[ 'label' ] = str(splitedLabel[0])
return options
class MonitoringSpot_InLine_FORM( forms.ModelForm ):
class Meta:
model = MonitoringSpotClass
fields = [ 'monitoringSpot_NODE_monitoringAreaType', ]
widgets = {
'monitoringSpot_NODE_monitoringAreaType': OptionAttr( attributes = { 'extra': True } )
}
If you set True to extra attribute this code will split all data from LABEL into a extra tag. Or you can set your own value.

Django 2.0.7. is missing the complete path in url when the user try to upload a file. It works on local enviroment but not in production server

I have a model with a ImageField:
class Usr( User ):
idusuario = models.AutoField( primary_key = True )
usuario = models.CharField( blank = False, unique = True, max_length = 50 )
contraseña = models.CharField( blank = False, max_length = 250 )
telefono = models.CharField( max_length = 15, blank = True, null = True )
celular = models.CharField( max_length = 15, blank = True, null = True )
fotografia = models.ImageField( blank = True, null = True, upload_to = 'usuarios' )
depende_de = models.ForeignKey( 'self', on_delete = models.CASCADE, related_name = '+', blank = True, null = True )
def __unicode__( self ):
return self.get_full_name()
def __str__( self ):
return self.get_full_name()
And its form (a ModelForm ):
class RegUsuario( forms.ModelForm ):
class Meta:
model = Usr
fields = [
'usuario',
'contraseña',
'is_active',
'is_superuser',
'first_name',
'last_name',
'email',
'telefono',
'celular',
'fotografia',
'groups',
'depende_de'
]
In views (vw_usuario.py) I have:
#valida_acceso( [ 'usr.agregar_usuarios_usuario' ] )
def new( request ):
if 'POST' == request.method:
frm = RegUsuario( request.POST, files = request.FILES )
if frm.is_valid():
obj = frm.save( commit = False )
obj.username = obj.usuario
obj.set_password( obj.contraseña )
obj.save()
for g in request.POST.getlist( 'groups' ):
obj.groups.add( g )
obj.save()
return HttpResponseRedirect( reverse( 'usuario_ver', kwargs = { 'pk' : obj.pk } ) )
frm = RegUsuario( request.POST or None )
return render( request, 'global/form.html', {
'menu_main' : Usr.objects.filter( id = request.user.pk )[ 0 ].main_menu_struct(),
'footer' : True,
'titulo' : 'Usuarios',
'titulo_descripcion' : 'Nuevo',
'frm' : frm
} )
And in urls.py:
urlpatterns = [
...
path( 'usuarios/nuevo/', vw_usuario.new, name = "usuario_nuevo" ),
...
]
If I go to http://example.com/usuarios/nuevo/ in the browser I can the form displayed as well, then I fill the fields and submit the form, and I got the exception:
Page not found (404)
Request Method: POST
Request URL: http://example.com/usuarios/nuevo/
Raised by: seguridad.mkitsafe.validacion
Using the URLconf defined in example.urls, Django tried these URL patterns, in this order:
...
usuarios/eliminar/<pk>/ [name= usuario_eliminar ]
usuarios/nuevo/ [name= usuario_nuevo ]
usuarios/<pk>/ [name= usuario_ver ]
...
The current path, nuevo/, didn t match any of these.
I don't understand why the url is taken as nuevo/ instead of usuarios/nuevo/
In the form template I'm setting method = "post", enctype="multipart/form-data" and action="" (I've also tried action="usuarios/nuevo" and action="http://example.com/usuarios/nuevo/")
The path for MEDIA_ROOT exists and has enough perms.
The issue happens if I fill in the form the ImageField field or not.
I noticed that if I remove the field in the modelform, everything works as well.
The source code for seguridad.mkitsafe.validacion is:
def valida_acceso( permisos = None ):
url_error = 'seguridad_inicio'
url_autenticacion = 'seguridad_login'
def _valida_acceso( vista ):
def validacion( *args, **kwargs ):
usuario = args[ 0 ].user
if not usuario.is_authenticated:
print_error( "Vista {} negada por autenticación".format( vista.__name__ ), "Exec Info" )
return HttpResponseRedirect( reverse( url_autenticacion ) )
if permisos is None:
return vista( *args, **kwargs )
perms = []
for perm in permisos:
permiso = Permiso.get_from_package_codename( perm )
if( permiso is None ):
print_error( "No se ha encontrado el permiso: " + perm )
else:
perms.append( permiso.perm() )
desc = permiso.descendencia()
for p in desc:
perms.append( p.perm() )
for perm in perms:
p = "{}.{}".format( perm.content_type.app_label, perm.codename )
if usuario.has_perm( p ):
return vista( *args, **kwargs )
print_error( "Vista {} negada por permisos {}".format( vista.__name__, permisos ), "Exec Info" )
return HttpResponseRedirect( reverse( url_error ) )
return validacion
return _valida_acceso
And it is a decorator which verify perms and authentication.
If I remove this decorator the excepion changes in the Raised by to seguridad.vw_usuario.new
Page not found (404)
Request Method: POST
Request URL: http://example.com/usuarios/nuevo/
Raised by: seguridad.vw_usuario.new
Using the URLconf defined in example.urls, Django tried these URL patterns, in this order:
admin/
...
usuarios/actualizar/<pk>/ [name='usuario_actualizar']
usuarios/eliminar/<pk>/ [name='usuario_eliminar']
usuarios/nuevo/ [name='usuario_nuevo']
usuarios/<pk>/ [name='usuario_ver']
usuarios/ [name='usuario_inicio']
...
The current path, nuevo/, didn't match any of these.
I also noticed that when the error is raised and the decorator is active the decorator or the view function is not called.
I also tried to copy a file in MEDIA_ROOT path with an script and it worked as well, so the script has right access to this path.
Any comment about the issue?

Flask-admin UserWarning: Fields missing from ruleset

When executing my Flask application I get the following warnings:
C:\Python27\lib\site-packages\flask_admin\model\base.py:1324: UserWarning: Fields missing from ruleset: password
warnings.warn(text)
C:\Python27\lib\site-packages\flask_admin\model\base.py:1324: UserWarning: Fields missing from ruleset: new_password
warnings.warn(text)
* Restarting with stat
C:\Python27\lib\site-packages\flask_admin\model\base.py:1324: UserWarning: Fields missing from ruleset: password
warnings.warn(text)
C:\Python27\lib\site-packages\flask_admin\model\base.py:1324: UserWarning: Fields missing from ruleset: new_password
warnings.warn(text)
I've normally used form_excluded_columns to remove unwanted fields from my form, but this time I have a hard time to get rid of those errors.
Here's my view:
class AdministratorView(sqla.ModelView):
page_size = 10
column_searchable_list = (
'username',
'description'
)
column_list = (
'username',
'apikey',
'description',
'active'
)
column_exclude_list = list = (
'apikey',
'source'
)
form_excluded_columns = (
'source',
'photos'
)
column_labels = {
'apikey': 'API Key'
}
form_widget_args = {
'apikey':{
'readonly':True
}
}
form_create_rules = (
rules.FieldSet(('username', 'password', 'description'), 'Personal'),
rules.FieldSet(('roles', 'apikey', 'active'), 'Permission'),
)
form_edit_rules = (
rules.FieldSet(('username', 'description'), 'Personal'),
rules.FieldSet(('roles', 'apikey', 'active'), 'Permission'),
rules.Header('Reset password'),
rules.Field('new_password')
)
def on_model_change(self, form, model, is_created):
if is_created is False:
if form.new_password.data:
model.password = generate_password_hash(form.new_password.data)
def scaffold_form(self):
form_class = super(AdministratorView, self).scaffold_form()
form_class.password = fields.PasswordField('Password', [validators.Required()])
form_class.new_password = fields.PasswordField('New Password')
return form_class
def is_accessible(self):
if login.current_user.is_authenticated:
return login.current_user.has_role('admin')
The purpose of this view is to have a single, required Password-field on the create form and a optional "New password"-field on the edit-form. I understand that the warnings arise when I don't include password/new_password in form_create_rules and form_edit_rules, but adding those fields to form_excluded_columns doesn't fix it.
Any tips on how I can get rid of the warnings?
Edit:
I suppose I should rather use get_create_form and get_edit_form instead of only scaffold_form. One benefit is that this makes it easier to override each form separately. Can I simplify this further? Should I do requirement validation like this or add nullable=False to the database schema (SQLAlchemy)?
class AdministratorView(sqla.ModelView):
page_size = 10
column_searchable_list = (
'username',
'description'
)
column_list = (
'username',
'apikey',
'description',
'active'
)
column_exclude_list = list = (
'apikey',
'source'
)
form_excluded_columns = (
'source',
'photos'
)
column_labels = {
'apikey': 'API Key'
}
form_widget_args = {
'apikey':{
'readonly':True
}
}
form_create_rules = (
rules.FieldSet(('username', 'password', 'description'), 'Personal'),
rules.FieldSet(('roles', 'apikey', 'active'), 'Permission'),
)
form_edit_rules = (
rules.FieldSet(('username', 'description'), 'Personal'),
rules.FieldSet(('roles', 'apikey', 'active'), 'Permission'),
rules.Header('Reset password'),
rules.Field('new_password')
)
def get_create_form(self):
form = self.scaffold_form()
form.username = fields.StringField('Username', [validators.Required()])
form.password = fields.PasswordField('Password', [validators.Required()])
return form
def get_edit_form(self):
form = self.scaffold_form()
delattr(form, 'password')
form.new_password = fields.PasswordField('New Password')
return form
def on_model_change(self, form, model, is_created):
if is_created is False:
if form.new_password.data:
model.password = generate_password_hash(form.new_password.data)
def is_accessible(self):
if login.current_user.is_authenticated:
return login.current_user.has_role('admin')
Perhaps this will help: How can I avoid Flask-Admin 2.1 warning "UserWarning: Fields missing from ruleset"?
Here's the relevant code from that answer:
import warnings
with warnings.catch_warnings():
warnings.filterwarnings('ignore', 'Fields missing from ruleset', UserWarning)
admin.add_view(UserView())

Customize Django Admin: Add More Than One Default Inline on Parent Add_View

I have an admin model with a few inline models included with it (see the ResourceUserAdmin model below for full class):
inlines = [
ResourceLocationInlineAdmin ,
ResourceCategoryInlineAdmin ,
ResourceStageInlineAdmin ,
]
When a user clicks to create a new ResourceUserAdmin I want the inlines of the class ResourceCategoryInlineAdmin to get initial values -- note that these relationships will not be saved to the database. I've tried to override parts of the add_view function to get what i want but I can't figure out how to pass multiple inline forms back to parent.
Any ideas on how to achieve this?
Models
class ResourceUserAdmin( admin.ModelAdmin ):
inlines = [
ResourceLocationInlineAdmin ,
ResourceCategoryInlineAdmin ,
ResourceStageInlineAdmin ,
]
list_display = (
'user' ,
'name' ,
'state' ,
'email' ,
'website' ,
'phone' ,
'logo_url_link',
)
search_fields = ( 'name' , 'email' , 'website' )
list_filter = ( 'name' , 'state' , 'email' , 'website' )
ordering = ( 'name', )
fields = (
'user' ,
'name' ,
'state' ,
'email' ,
'website' ,
'phone' ,
'logo' ,
'ideal_candidate',
)
admin.site.register( ResourceUser, ResourceUserAdmin )
Here is the inline model I want to create many by default:
class ResourceCategoryInlineAdmin( admin.StackedInline ):
model = ResourceCategory
extra = 0
class ResourceCategoryAdmin( admin.ModelAdmin ):
list_display = ( 'user' ,
'category' , )
ordering = ( 'user' , )
fields = ( 'user' , 'category' )
def formfield_for_foreignkey( self, db_field, *args, **kwargs ):
if isinstance( db_field, models.ForeignKey ):
if db_field.name == 'category':
kwargs['widget'] = forms.RadioSelect()
return super( ResourceCategoryAdmin, self).formfield_for_foreignkey( db_field, **kwargs )
admin.site.register( ResourceCategory, ResourceCategoryAdmin )
This is one solution, though not the option i really wanted to use. You can do it by overriding the the whole add_view function and setting the intial attributes for each form in the formsets (look for the override comment below)
def add_view(self, request, form_url='', extra_context=None):
"The 'add' admin view for this model."
model = self.model
opts = model._meta
if not self.has_add_permission(request):
raise PermissionDenied
ModelForm = self.get_form(request)
formsets = []
if request.method == 'POST':
form = ModelForm(request.POST, request.FILES)
if form.is_valid():
new_object = self.save_form(request, form, change=False)
form_validated = True
else:
form_validated = False
new_object = self.model()
prefixes = {}
for FormSet, inline in zip(self.get_formsets(request), self.inline_instances):
prefix = FormSet.get_default_prefix()
prefixes[prefix] = prefixes.get(prefix, 0) + 1
if prefixes[prefix] != 1:
prefix = "%s-%s" % (prefix, prefixes[prefix])
formset = FormSet(data=request.POST, files=request.FILES,
instance=new_object,
save_as_new="_saveasnew" in request.POST,
prefix=prefix, queryset=inline.queryset(request))
formsets.append(formset)
if all_valid(formsets) and form_validated:
self.save_model(request, new_object, form, change=False)
form.save_m2m()
for formset in formsets:
self.save_formset(request, form, formset, change=False)
self.log_addition(request, new_object)
return self.response_add(request, new_object)
else:
# Prepare the dict of initial data from the request.
# We have to special-case M2Ms as a list of comma-separated PKs.
initial = dict(request.GET.items())
for k in initial:
logger.info( "for k in initial, k = %s" % k )
try:
f = opts.get_field(k)
except models.FieldDoesNotExist:
continue
if isinstance(f, models.ManyToManyField):
initial[k] = initial[k].split(",")
form = ModelForm(initial=initial)
prefixes = {}
for FormSet, inline in zip(self.get_formsets(request),
self.inline_instances):
prefix = FormSet.get_default_prefix()
prefixes[prefix] = prefixes.get(prefix, 0) + 1
if prefixes[prefix] != 1:
prefix = "%s-%s" % (prefix, prefixes[prefix])
formset = FormSet(instance=self.model(), prefix=prefix, queryset=inline.queryset(request))
#
#
# override the inlines of my choice
# to create initial values
#
#
if inline.__class__.__name__ == 'ResourceCategoryInlineAdmin':
for frm, category in zip( formset, Category.objects.all() ):
frm.fields['category'].initial = category
formsets.append(formset)
adminForm = helpers.AdminForm(form, list(self.get_fieldsets(request)),
self.prepopulated_fields, self.get_readonly_fields(request),
model_admin=self)
media = self.media + adminForm.media
inline_admin_formsets = []
for inline, formset in zip(self.inline_instances, formsets):
fieldsets = list(inline.get_fieldsets(request))
readonly = list(inline.get_readonly_fields(request))
inline_admin_formset = helpers.InlineAdminFormSet(inline, formset,
fieldsets, readonly, model_admin=self)
inline_admin_formsets.append(inline_admin_formset)
media = media + inline_admin_formset.media
context = {
'title': _('Add %s') % force_unicode(opts.verbose_name),
'adminform': adminForm,
'is_popup': "_popup" in request.REQUEST,
'show_delete': False,
'media': mark_safe(media),
'inline_admin_formsets': inline_admin_formsets,
'errors': helpers.AdminErrorList(form, formsets),
'root_path': self.admin_site.root_path,
'app_label': opts.app_label,
}
context.update(extra_context or {})
return self.render_change_form(request, context, form_url=form_url, add=True)
#return super(ResourceUserAdmin, self).add_view(request, form_url=form_url, extra_context=extra_context)