def _login_view(request): """Standard Django login plus lowercases the login email(username)""" if request.method == "POST": redirect_to = request.REQUEST.get('next', False) form = LoginForm(request.POST) if form.is_valid(): new_user = authenticate( username=form.cleaned_data['email'].lower(), password=form.cleaned_data['password'] ) if new_user and new_user.is_active: login(request, new_user) if redirect_to: return HttpResponseRedirect(redirect_to) else: return HttpResponseRedirect(reverse("seed:home")) else: errors = ErrorList() errors = form._errors.setdefault(NON_FIELD_ERRORS, errors) errors.append('Username and/or password were invalid.') else: form = LoginForm() return locals()
def clean_sub_fields(self, value): """'value' being the list of the values of the subfields, validate each subfield.""" clean_data = [] errors = ErrorList() # Remove the field corresponding to the SKIP_CHECK_NAME boolean field # if required. fields = self.fields if not self.skip_check else self.fields[:-1] for index, field in enumerate(fields): try: field_value = value[index] except IndexError: field_value = None # Check the field's 'required' field instead of the global # 'required' field to allow subfields to be required or not. if field.required and field_value in validators.EMPTY_VALUES: errors.append( '%s: %s' % (field.label, self.error_messages['required'])) continue try: clean_data.append(field.clean(field_value)) except ValidationError, e: # Collect all validation errors in a single list, which we'll # raise at the end of clean(), rather than raising a single # exception for the first error we encounter. errors.extend( ['%s: %s' % (field.label, message) for message in e.messages])
def clean(self, value): """ Take a tuple of fields_valie(dict) and json_value(str) from JSONWidget """ fields_value, json_value = value errors = ErrorList() # Clear json value if isinstance(json_value, basestring): try: json_value = loads(json_value) except ValueError: json_value = None errors.append(_(u"JSON Field: Enter valid JSON")) if json_value != None and not isinstance(json_value, dict): errors.append(_(u"JSON Field: Must be a dict")) # Clear fields assert isinstance(fields_value, dict) if json_value: merge_dict(fields_value, json_value) def _clean(f, _values): for k, v in iterhelper(f): if isinstance(v, (dict, tuple, list)): _clean(v, _values.get(k, {})) else: try: tmp = _values.get(k, None) v.clean(tmp) _values[k] = v.to_python(tmp) except FormValidationError, e: errors.extend( map(lambda x, y: x + y, [u"%s %s: " % (_("Field"), k)] * len(e.messages), e.messages) )
def lib_artist(request, artist_name): artist_name_comma = Artist.commafy(artist_name) artist = get_object_or_none(Artist, name=artist_name_comma) if (artist is None): artist = get_object_or_none(Artist, name=artist_name) errors = ErrorList() albums = [] similar_artists = [] artist_art = '' api = PyLastFm() art_api = EchoNest() if artist is not None: albums = Album.objects.filter(artist=artist).order_by("-date_released") if albums.count() > 0: lfm_artist = get_last_fm_artist_name(artist) if lfm_artist: similar_artists = [similar for similar in api.get_similar_artists(lfm_artist) if Artist.objects.filter(name__iexact=similar).count() > 0 or Artist.objects.filter(name__iexact=Artist.commafy(similar)).count() > 0 ] artist_art = art_api.get_artist_art(lfm_artist) else: errors.append('The artist could not be found by Last.Fm') return render_to_response('artist.html', { 'errors': errors, 'albums': albums, 'artist': artist, 'artist_art': artist_art, 'similar_artists': similar_artists, }, context_instance=RequestContext(request))
def form_valid(self, form): with transaction.commit_manually(): try: super(ItemCreate, self).form_valid(form) except ValidationError as e: transaction.rollback() errors = ErrorList() for error in e.messages: errors.append(error) errors = form._errors.setdefault(NON_FIELD_ERRORS, errors) return super(ItemCreate, self).form_invalid(form) context = self.get_context_data() itemimage_form = context['itemimage_formset'] if itemimage_form.is_valid(): itemimage_form.save() transaction.commit() return redirect(self.get_success_url()) else: transaction.rollback() return self.render_to_response( self.get_context_data(form=form) )
def clean_sub_fields(self, value): """'value' being the list of the values of the subfields, validate each subfield.""" clean_data = [] errors = ErrorList() # Remove the field corresponding to the SKIP_CHECK_NAME boolean field # if required. fields = self.fields if not self.skip_check else self.fields[:-1] for index, field in enumerate(fields): try: field_value = value[index] except IndexError: field_value = None # Check the field's 'required' field instead of the global # 'required' field to allow subfields to be required or not. if field.required and field_value in validators.EMPTY_VALUES: errors.append('%s: %s' % (field.label, self.error_messages['required'])) continue try: clean_data.append(field.clean(field_value)) except ValidationError, e: # Collect all validation errors in a single list, which we'll # raise at the end of clean(), rather than raising a single # exception for the first error we encounter. errors.extend('%s: %s' % (field.label, message) for message in e.messages)
def lib_main(request): albums = [] errors = ErrorList() pager = Paginator([], 1) selected_page = 1 form = None # it's our search form # If a form was just submitted if request.method == 'POST': form = SearchForm(request.POST) # A form bound to the POST data if form.is_valid(): # Use the form fields to search and filter albums from the db albums = lib_main_filter_albums(form) pager = Paginator(albums, form.cleaned_data['items_per_page']) selected_page = int(form.cleaned_data['selected_page']) page_list = [(str(x), str(x)) for x in pager.page_range][:100] if len(page_list) is 0: form.fields['selected_page'][('1', '1')] else: form.fields['selected_page'].choices = page_list form.fields['selected_page'].initial = selected_page else: # Add all of the errors in the form.errors dict to our error list errors.extend(chain.from_iterable(form.errors.values())) form.save() else: form = SearchForm( initial={ 'artist': request.GET.get('artist'), 'album': request.GET.get('album'), 'label': request.GET.get('label'), 'year': request.GET.get('year'), 'genre': request.GET.get('genre'), 'stack': request.GET.get('stack'), 'selected_page': "1", 'items_per_page': "25", }) form.fields['selected_page'].choices = [ (str(x), str(x)) for x in pager.page_range ][:100] albums_page = [] try: albums_page = pager.page(selected_page).object_list except EmptyPage: albums_page = pager.page(1).object_list errors.append("That page is empty.") return render_to_response('library.html', { 'form': form, 'albums': albums_page, 'errors': errors, }, context_instance=RequestContext(request))
def clean(self, value): """ Validates every value in the given list. A value is validated against the corresponding Field in self.fields. For example, if this MultiValueField was instantiated with fields=(DateField(), TimeField()), clean() would call DateField.clean(value[0]) and TimeField.clean(value[1]). """ clean_data = [] errors = ErrorList() if not value or isinstance(value, (list, tuple)): if not value or not [ v for v in value if v not in self.empty_values ]: if self.required: raise ValidationError(self.error_messages['required'], code='required') else: return self.compress([]) else: raise ValidationError(self.error_messages['invalid'], code='invalid') for i, field in enumerate(self.fields): try: field_value = value[i] except IndexError: field_value = None if field_value in self.empty_values: if self.require_all_fields: # Raise a 'required' error if the MultiValueField is # required and any field is empty. if self.required: raise ValidationError(self.error_messages['required'], code='required') elif field.required: # Otherwise, add an 'incomplete' error to the list of # collected errors and skip field cleaning, if a required # field is empty. if field.error_messages['incomplete'] not in errors: errors.append(field.error_messages['incomplete']) continue try: clean_data.append(field.clean(field_value)) except ValidationError as e: # Collect all validation errors in a single list, which we'll # raise at the end of clean(), rather than raising a single # exception for the first error we encounter. Skip duplicates. errors.extend(m for m in e.error_list if m not in errors) if errors: raise ValidationError(errors) out = self.compress(clean_data) self.validate(out) self.run_validators(out) return out
def form_valid(self, form): try: return super(ExhibitionCreate, self).form_valid(form) except ValidationError as e: errors = ErrorList() for error in e.messages: errors.append(error) errors = form._errors.setdefault(NON_FIELD_ERRORS, errors) return super(ExhibitionCreate, self).form_invalid(form)
def lib_main(request): albums = [] errors = ErrorList() pager = Paginator([], 1) selected_page = 1 form = None # it's our search form # If a form was just submitted if request.method == 'POST': form = SearchForm(request.POST) # A form bound to the POST data if form.is_valid(): # Use the form fields to search and filter albums from the db albums = lib_main_filter_albums(form) pager = Paginator(albums, form.cleaned_data['items_per_page']) selected_page = int(form.cleaned_data['selected_page']) page_list = [(str(x), str(x)) for x in pager.page_range][:100] if len(page_list) is 0: form.fields['selected_page'][('1', '1')] else: form.fields['selected_page'].choices = page_list form.fields['selected_page'].initial = selected_page else: # Add all of the errors in the form.errors dict to our error list errors.extend(chain.from_iterable(form.errors.values())) form.save() else: form = SearchForm(initial={'artist': request.GET.get('artist'), 'album': request.GET.get('album'), 'label': request.GET.get('label'), 'year': request.GET.get('year'), 'genre': request.GET.get('genre'), 'stack': request.GET.get('stack'), 'selected_page': "1", 'items_per_page': "25", }) form.fields['selected_page'].choices = [(str(x), str(x)) for x in pager.page_range][:100] albums_page = [] try: albums_page = pager.page(selected_page).object_list except EmptyPage: albums_page = pager.page(1).object_list errors.append("That page is empty.") return render_to_response('library.html', { 'form': form, 'albums': albums_page, 'errors': errors, }, context_instance=RequestContext(request))
def login_view(request): """ Standard Django login, with additions: Lowercase the login email (username) Check user has accepted ToS, if any. """ if request.method == "POST": redirect_to = request.REQUEST.get('next', False) if not redirect_to: redirect_to = reverse('seed:home') form = LoginForm(request.POST) if form.is_valid(): new_user = authenticate( username=form.cleaned_data['email'].lower(), password=form.cleaned_data['password'] ) if new_user and new_user.is_active: # determine if user has accepted ToS, if one exists try: user_accepted_tos = has_user_agreed_latest_tos(new_user) except NoActiveTermsOfService: # there's no active ToS, skip interstitial user_accepted_tos = True if user_accepted_tos: login(request, new_user) return HttpResponseRedirect(redirect_to) else: # store login info for django-tos to handle request.session['tos_user'] = new_user.pk request.session['tos_backend'] = new_user.backend context = RequestContext(request) context.update({ 'next': redirect_to, 'tos': TermsOfService.objects.get_current_tos() }) return render_to_response( 'tos/tos_check.html', context_instance=context ) else: errors = ErrorList() errors = form._errors.setdefault(NON_FIELD_ERRORS, errors) errors.append('Username and/or password were invalid.') else: form = LoginForm() return render_to_response( 'landing/login.html', locals(), context_instance=RequestContext(request), )
def clean(self, value): """ Validates every value in the given list. A value is validated against the corresponding Field in self.fields. For example, if this MultiValueField was instantiated with fields=(DateField(), TimeField()), clean() would call DateField.clean(value[0]) and TimeField.clean(value[1]). """ clean_data = [] errors = ErrorList() if not value or isinstance(value, (list, tuple)): if not value or not [v for v in value if v not in self.empty_values]: if self.required: raise ValidationError(self.error_messages['required'], code='required') else: return self.compress([]) else: raise ValidationError(self.error_messages['invalid'], code='invalid') for i, field in enumerate(self.fields): try: field_value = value[i] except IndexError: field_value = None if field_value in self.empty_values: if self.require_all_fields: # Raise a 'required' error if the MultiValueField is # required and any field is empty. if self.required: raise ValidationError(self.error_messages['required'], code='required') elif field.required: # Otherwise, add an 'incomplete' error to the list of # collected errors and skip field cleaning, if a required # field is empty. if field.error_messages['incomplete'] not in errors: errors.append(field.error_messages['incomplete']) continue try: clean_data.append(field.clean(field_value)) except ValidationError as e: # Collect all validation errors in a single list, which we'll # raise at the end of clean(), rather than raising a single # exception for the first error we encounter. Skip duplicates. errors.extend(m for m in e.error_list if m not in errors) if errors: raise ValidationError(errors) out = self.compress(clean_data) self.validate(out) self.run_validators(out) return out
def errors_append(form, field_name, message): u""" Add an ValidationError to a field (instead of __all__) during Form.clean(): class MyForm(forms.Form): def clean(self): value_a=self.cleaned_data['value_a'] value_b=self.cleaned_data['value_b'] if value_a==... and value_b==...: formutils.errors_append(self, 'value_a', u'Value A must be ... if value B is ...') return self.cleaned_data """ error_list = form.errors.get(field_name) if error_list is None: error_list = ErrorList() form.errors[field_name] = error_list error_list.append(message)
def _validate_fields(self): """ Validate individual field values, like django's clean_<fieldname> with less magic ( no setattr('clean_'+field_name) junk) just loop over the fields and apply the validators specified in the field spec (self._get_expected_fields_for_row(row)) """ cleaned_data = {} errors = ErrorList() for row_num, row in enumerate(self.rows): expected_fields = self._get_validators_for_row(row) if len(row) != len(expected_fields): raise serializers.ValidationError( "Row: %s - Incorrect number of columns should be %s " "actually %s" % (row_num + 1, len(expected_fields), len(row))) for idx, field_name in enumerate(expected_fields): field_value = row[idx] validators = expected_fields[field_name] try: cleaned_data[field_name] = self._validate_field( field_name, field_value.strip(), idx, row_num, validators) except serializers.ValidationError as ve: errors.append(ve) except (AssertionError, TypeError) as e: errors.append(e) try: # Global Validation applicable_contract = self._get_applicable_contract_for_row( row) self.cleaned_data.append( self._validate_data(cleaned_data, row_num, applicable_contract)) except serializers.ValidationError as ve: errors.extend(ve.error_list) if len(errors): raise serializers.ValidationError(errors)
def lib_album(request, artist_name, album_title): errors = ErrorList() songs = [] album_art = '' api = PyLastFm() album = get_object_or_none(Album, artist__name__iexact=artist_name, name__iexact=album_title) artist = get_object_or_none(Artist, name__iexact=artist_name) if album is not None and artist is not None: # Check if we have the track listing in our database songs = Song.objects.filter(album=album).order_by('track_num') try: lfm_artist = get_last_fm_artist_name(artist) album_art = api.get_album_art(lfm_artist, album.name) # If not, get the track listing from Last.fm and save it. if songs.count() == 0: songs = save_track_list(album) except WSError: errors.append('The album or artist could not be found by Last.Fm') else: if artist is None: errors.append('The artist was not found in the WUVT Library.') if album is None: errors.append('The album was not found in the WUVT library.') return render_to_response('album.html', { 'errors': errors, 'album': album, 'album_art': album_art, 'songs': songs, }, context_instance=RequestContext(request))
def clean(self): """ Ensure that the two password are equal and that the two email addresses are equal. """ cleaned_data = self.cleaned_data errors = self._errors if not errors.get("txtEmail"): email1 = cleaned_data.get("txtEmail") email2 = cleaned_data.get("txtEmailAgain") if email1 != email2: error_message = ( u"The email fields did not contain the same address. " + u"Make sure the address is written correctly.") error_list = errors.get("txtEmailAgain") if not error_list: error_list = ErrorList() error_list.append(error_message) errors["txtEmailAgain"] = error_list if not errors.get("txtPassword"): password1 = cleaned_data.get("txtPassword") password2 = cleaned_data.get("txtPasswordAgain") if password1 != password2: error_message = ( u"The password fields did not contain the same password. " + u"Make sure the password is written correctly.") error_list = errors.get("txtPasswordAgain") if not error_list: error_list = ErrorList() error_list.append(error_message) errors["txtPasswordAgain"] = error_list self._errors = errors return cleaned_data
def form_errors_append(form, field_name, message): ''' Add an ValidationError to a field (instead of __all__) during Form.clean(): class MyForm(forms.Form): def clean(self): value_a=self.cleaned_data['value_a'] value_b=self.cleaned_data['value_b'] if value_a==... and value_b==...: formutils.errors_append(self, 'value_a', u'Value A must be ... if value B is ...') return self.cleaned_data ''' assert form.fields.has_key(field_name), field_name error_list = form.errors.get(field_name) if error_list is None: error_list = ErrorList() form.errors[field_name] = error_list elif error_list[ -1] == message: #FIXME, unicode isn't comparable with str, message in error list cannot work so only two messages are allowed return error_list.append(message)
def _validate_fields(self): """ Validate individual field values, like django's clean_<fieldname> with less magic ( no setattr('clean_'+field_name) junk) just loop over the fields and apply the validators specified in the field spec (self._get_expected_fields_for_row(row)) """ cleaned_data = {} errors = ErrorList() for row_num, row in enumerate(self.rows): expected_fields = self._get_validators_for_row(row) if len(row) != len(expected_fields): raise serializers.ValidationError( "Row: %s - Incorrect number of columns should be %s " "actually %s" % (row_num + 1, len(expected_fields), len(row)) ) for idx, field_name in enumerate(expected_fields): field_value = row[idx] validators = expected_fields[field_name] try: cleaned_data[field_name] = self._validate_field( field_name, field_value.strip(), idx, row_num, validators ) except serializers.ValidationError as ve: errors.append(ve) except (AssertionError, TypeError) as e: errors.append(e) try: # Global Validation applicable_contract = self._get_applicable_contract_for_row(row) self.cleaned_data.append(self._validate_data(cleaned_data, row_num, applicable_contract)) except serializers.ValidationError as ve: errors.extend(ve.error_list) if len(errors): raise serializers.ValidationError(errors)
def lib_artist(request, artist_name): artist_name_comma = Artist.commafy(artist_name) artist = get_object_or_none(Artist, name=artist_name_comma) if (artist is None): artist = get_object_or_none(Artist, name=artist_name) errors = ErrorList() albums = [] similar_artists = [] artist_art = '' api = PyLastFm() art_api = EchoNest() if artist is not None: albums = Album.objects.filter(artist=artist).order_by("-date_released") if albums.count() > 0: lfm_artist = get_last_fm_artist_name(artist) if lfm_artist: similar_artists = [ similar for similar in api.get_similar_artists(lfm_artist) if Artist.objects.filter(name__iexact=similar).count() > 0 or Artist.objects.filter( name__iexact=Artist.commafy(similar)).count() > 0 ] artist_art = art_api.get_artist_art(lfm_artist) else: errors.append('The artist could not be found by Last.Fm') return render_to_response('artist.html', { 'errors': errors, 'albums': albums, 'artist': artist, 'artist_art': artist_art, 'similar_artists': similar_artists, }, context_instance=RequestContext(request))
def clean(self): """ Ensure that the two password are equal and that the two email addresses are equal. """ cleaned_data = self.cleaned_data errors = self._errors if not errors.get("txtEmail"): email1 = cleaned_data.get("txtEmail") email2 = cleaned_data.get("txtEmailAgain") if email1 != email2: error_message = (u"The email fields did not contain the same address. " + u"Make sure the address is written correctly.") error_list = errors.get("txtEmailAgain") if not error_list: error_list = ErrorList() error_list.append(error_message) errors["txtEmailAgain"] = error_list if not errors.get("txtPassword"): password1 = cleaned_data.get("txtPassword") password2 = cleaned_data.get("txtPasswordAgain") if password1 != password2: error_message = (u"The password fields did not contain the same password. " + u"Make sure the password is written correctly.") error_list = errors.get("txtPasswordAgain") if not error_list: error_list = ErrorList() error_list.append(error_message) errors["txtPasswordAgain"] = error_list self._errors = errors return cleaned_data
def _validate_data(self, cleaned_data, row_num, applicable_contract): """ Like django's clean method, use this to validate across fields """ errors = ErrorList() validation_methods = [ self._validate_open_closed_date, self._validate_service_adaptation, self._validate_media_code, self._validate_stage_reached, self._validate_dob_present, ] validation_methods.extend( self.get_extra_validators_for_applicable_contract( applicable_contract)) validation_methods_depend_on_category = [ self._validate_time_spent, self._validate_exemption, self._validate_telephone_or_online_advice, self._validate_determination_dvca_is_family, ] for m in validation_methods: try: m(cleaned_data) except serializers.ValidationError as ve: errors.append(self.format_message(ve.message, row_num)) try: category = self._validate_category_consistency(cleaned_data) except serializers.ValidationError as ve: errors.append(self.format_message(ve.message, row_num)) raise serializers.ValidationError(errors) for m in validation_methods_depend_on_category: try: m(cleaned_data, category) except serializers.ValidationError as ve: errors.append(self.format_message(ve.message, row_num)) if len(errors): raise serializers.ValidationError(errors) return cleaned_data
def _validate_data(self, cleaned_data, row_num, applicable_contract): """ Like django's clean method, use this to validate across fields """ errors = ErrorList() validation_methods = [ self._validate_open_closed_date, self._validate_service_adaptation, self._validate_media_code, self._validate_stage_reached, self._validate_dob_present, ] validation_methods.extend(self.get_extra_validators_for_applicable_contract(applicable_contract)) validation_methods_depend_on_category = [ self._validate_time_spent, self._validate_exemption, self._validate_telephone_or_online_advice, self._validate_determination_dvca_is_family, ] for m in validation_methods: try: m(cleaned_data) except serializers.ValidationError as ve: errors.append(self.format_message(ve.message, row_num)) try: category = self._validate_category_consistency(cleaned_data) except serializers.ValidationError as ve: errors.append(self.format_message(ve.message, row_num)) raise serializers.ValidationError(errors) for m in validation_methods_depend_on_category: try: m(cleaned_data, category) except serializers.ValidationError as ve: errors.append(self.format_message(ve.message, row_num)) if len(errors): raise serializers.ValidationError(errors) return cleaned_data
class PLMObject(AbstractPLMObject): u""" Base class for :class:`.Part` and :class:`.Document`. A PLMObject is identified by a triplet reference/type/revision :key attributes: .. attribute:: reference Reference of the :class:`.PLMObject`, for example ``YLTG00`` .. attribute:: type Type of the :class:`.PLMObject`, for example ``Game`` .. attribute:: revision Revision of the :class:`.PLMObject`, for example ``a`` :other attributes: .. attribute:: name Name of the product, for example ``Game of life`` .. attribute:: creator :class:`~django.contrib.auth.models.User` who created the :class:`.PLMObject` .. attribute:: creator :class:`~django.contrib.auth.models.User` who owns the :class:`.PLMObject` .. attribute:: ctime date of creation of the object (default value : current time) .. attribute:: mtime date of last modification of the object (automatically field at each save) .. attribute:: lifecycle :class:`.Lifecycle` of the object .. attribute:: state Current :class:`.State` of the object .. attribute:: group :class:`.GroupInfo` that owns the object .. attribute:: published .. versionadded:: 1.1 True if the object is published (accessible to anonymous user) .. attribute:: reference_number .. versionadded:: 1.1 number found in the reference if it matches ``PART_|DOC_\d+`` .. attribute:: description .. versionadded:: 2.0 a short description of the object. This field is optional and is a richtext field. .. note:: This class is abstract, to create a PLMObject, see :class:`.Part` and :class:`.Document`. .. versionchanged:: 1.1 :attr:`.published` and :attr:`.reference_number` added. """ # key attributes reference = models.CharField(_("reference"), max_length=50, db_index=True, help_text=_(u"Required. 50 characters or fewer. Letters, numbers , except #, ?, / and .. characters")) type = models.CharField(_("type"), max_length=50) revision = models.CharField(_("revision"), max_length=50) # hidden field to get a valid new reference reference_number = models.IntegerField(default=0) # other attributes name = models.CharField(_("name"), max_length=100, blank=True, help_text=_(u"Name of the product")) description = models.TextField(_("description"), blank=True, default="") description.richtext = True creator = models.ForeignKey(User, verbose_name=_("creator"), related_name="%(class)s_creator") owner = models.ForeignKey(User, verbose_name=_("owner"), related_name="%(class)s_owner") ctime = models.DateTimeField(_("date of creation"), default=timezone.now, auto_now_add=False) mtime = models.DateTimeField(_("date of last modification"), auto_now=True) group = models.ForeignKey(GroupInfo, verbose_name=_("group"), related_name="%(class)s_group") # state and lifecycle lifecycle = models.ForeignKey(Lifecycle, verbose_name=_("lifecycle"), related_name="+", default=get_default_lifecycle) state = models.ForeignKey(State, verbose_name=_("state"), related_name="+", default=get_default_state) published = models.BooleanField(verbose_name=_("published"), default=False) class Meta: # keys in the database app_label = "plmapp" unique_together = (('reference', 'type', 'revision'),) ordering = ["type", "reference", "revision"] def __init__(self, *args, **kwargs): # little hack: # get_creation_fields is a class method but it needs to create # an instance, this hack avoids calls to default value functions if "__fake__" not in kwargs: super(PLMObject, self).__init__(*args, **kwargs) self._promotion_errors = None self._title = None self._plmobject_url = None def __unicode__(self): return u"%s<%s/%s/%s>" % (type(self).__name__, self.reference, self.type, self.revision) @property def title(self): if self._title is None: attrs = tuple(esc(x) for x in [self.name, self.type, self.reference, self.revision]) self._title = mark_safe(u'''<span class="name">%s</span> (<span class="type">%s</span> // <span class="reference">%s</span> // <span class="revision">%s</span>)''' % attrs) return self._title def _is_promotable(self): """ Returns True if the object's state is the last state of its lifecycle. """ self._promotion_errors = ErrorList() if self.lifecycle.last_state == self.state: self._promotion_errors.append(_(u"The object is at its last state.")) return False return True def is_promotable(self): u""" Returns True if object is promotable .. note:: This method is abstract and raises :exc:`.NotImplementedError`. This method must be overriden. """ raise NotImplementedError() def _get_promotion_errors(self): """ Returns an :class:`.ErrorList` of promotion errors. Calls :meth:`.is_promotable()` if it has not already been called. """ if self._promotion_errors is None: self.is_promotable() return self._promotion_errors promotion_errors = property(_get_promotion_errors) @property def is_cloneable(self): """ .. versionadded:: 1.1 Return true by default. This property may be overriden by custom Part or Document """ return True @property def is_editable(self): """ True if the object is not in a non editable state """ return self.is_draft and not self.approvals.now().exists() @property @cache_lifecycle_stuff def is_proposed(self): """ True if the object is in a state prior to the official state but not draft. """ if self.is_cancelled or self.is_draft: return False lcs = self.lifecycle.lifecyclestates_set.only("rank") current_rank = lcs.get(state=self.state).rank official_rank = lcs.get(state=self.lifecycle.official_state).rank return current_rank < official_rank @property @cache_lifecycle_stuff def is_cancelled(self): """ True if the object is cancelled. """ return self.lifecycle == get_cancelled_lifecycle() @property @cache_lifecycle_stuff def is_deprecated(self): """ True if the object is deprecated. """ return not self.is_cancelled and self.state == self.lifecycle.last_state @property @cache_lifecycle_stuff def is_official(self): u"Returns True if object is official.""" return not self.is_cancelled and self.state == self.lifecycle.official_state @property @cache_lifecycle_stuff def is_draft(self): u""" Returns True if the object is a draft. """ return not self.is_cancelled and self.state == self.lifecycle.first_state @cache_lifecycle_stuff def get_current_sign_level(self): """ Returns the current sign level that a user must have to promote this object. """ rank = LifecycleStates.objects.get(state=self.state, lifecycle=self.lifecycle).rank return level_to_sign_str(rank) @cache_lifecycle_stuff def get_previous_sign_level(self): """ Returns the current sign level that a user must have to demote this object. """ rank = LifecycleStates.objects.get(state=self.state, lifecycle=self.lifecycle).rank return level_to_sign_str(rank - 1) @property def is_part(self): """ True if the plmobject is a part.""" from openPLM.plmapp.models.part import Part if self.type in get_all_plmobjects(): return issubclass(get_all_plmobjects()[self.type], Part) return False @property def is_document(self): """ True if the plmobject is a document.""" from openPLM.plmapp.models.document import Document if self.type in get_all_plmobjects(): return issubclass(get_all_plmobjects()[self.type], Document) return False @property def attributes(self): u"Attributes to display in `Attributes view`" return ["type", "reference", "revision", "name", "description", "creator", "owner", "group", "ctime", "mtime"] @property def published_attributes(self): u""".. versionadded:: 1.1 Attributes that are visible to everyone if the object has been published.""" return ["type", "reference", "revision", "name",] @property def menu_items(self): "Menu items to choose a view" return [ugettext_noop("attributes"), ugettext_noop("lifecycle"), ugettext_noop("revisions"), ugettext_noop("history"), ] @classmethod def excluded_creation_fields(cls): "Returns fields which should not be available in a creation form" return ["owner", "creator", "ctime", "mtime", "state"] @property def plmobject_url(self): if self._plmobject_url is None: url = u"/object/%s/%s/%s/" % (self.type, self.reference, self.revision) self._plmobject_url = iri_to_uri(url) return self._plmobject_url @classmethod def get_creation_fields(cls): """ Returns fields which should be displayed in a creation form. By default, it returns :attr:`.attributes` less attributes returned by :meth:`.excluded_creation_fields` """ fields = ["name", "group", "reference", "type", "revision", "lifecycle", "description"] excludes = cls.excluded_creation_fields() for field in cls(__fake__=True).attributes: if field not in excludes and field not in fields: fields.insert(2, field) return fields @classmethod def excluded_modification_fields(cls): """ Returns fields which should not be available in a modification form """ return [ugettext_noop("type"), ugettext_noop("reference"), ugettext_noop("revision"), ugettext_noop("ctime"), ugettext_noop("creator"), ugettext_noop("owner"), ugettext_noop("ctime"), ugettext_noop("mtime"), ugettext_noop("group")] @classmethod def get_modification_fields(cls): """ Returns fields which should be displayed in a modification form By default, it returns :attr:`.attributes` less attributes returned by :meth:`.excluded_modification_fields` """ fields = [] for field in cls(__fake__=True).attributes: if field not in cls.excluded_modification_fields(): fields.append(field) return fields def get_leaf_object(self): return get_all_plmobjects()[self.type].objects.get(id=self.id) def get_current_signer_role(self): lcl = self.lifecycle.to_states_list() return level_to_sign_str(lcl.index(self.state.name)) def get_current_signers(self): role = self.get_current_signer_role() return self.users.now().filter(role=role).values_list("user", flat=True) def get_approvers(self): if self.is_deprecated or self.is_cancelled: return self.approvals.none() lcl = self.lifecycle.to_states_list() next_state = lcl.next_state(self.state.name) approvers = self.approvals.now().filter(current_state=self.state, next_state=next_state).values_list("user", flat=True) return approvers
class ECR(models.Model, pmodels.IObject): u""" ECR (Engineering Change Request) model. :key attributes: .. attribute:: reference Reference of the :class:`.ECR`, for example ``ECR_0001`` :other attributes: .. attribute:: name Name of the ECR, for example ``Game of life`` .. attribute:: description long description of the ECR .. attribute:: creator :class:`~django.contrib.auth.models.User` who created the :class:`.ECR` .. attribute:: creator :class:`~django.contrib.auth.models.User` who owns the :class:`.ECR` .. attribute:: ctime date of creation of the object (default value : current time) .. attribute:: mtime date of last modification of the object (automatically field at each save) .. attribute:: lifecycle :class:`.Lifecycle` of the object .. attribute:: state Current :class:`.State` of the object .. attribute:: reference_number number found in the reference if it matches ``ECR_\d+`` """ # key attributes reference = models.CharField( _("reference"), max_length=50, db_index=True, unique=True, help_text= _(u"Required. 50 characters or fewer. Letters, numbers , except #, ?, / and .. characters" )) # hidden field to get a valid new reference reference_number = models.IntegerField(default=0) # other attributes name = models.CharField(_("name"), max_length=100, blank=True, help_text=_(u"Name of the ECR")) description = models.TextField(_("description"), blank=True) description.richtext = True creator = models.ForeignKey(User, verbose_name=_("creator"), related_name="%(class)s_creator") owner = models.ForeignKey(User, verbose_name=_("owner"), related_name="%(class)s_owner") ctime = models.DateTimeField(_("date of creation"), default=timezone.now, auto_now_add=False) mtime = models.DateTimeField(_("date of last modification"), auto_now=True) # state and lifecycle lifecycle = models.ForeignKey( pmodels.Lifecycle, verbose_name=_("lifecycle"), related_name="+", ) state = models.ForeignKey( pmodels.State, verbose_name=_("state"), related_name="+", ) class Meta: # keys in the database ordering = ["reference"] def __init__(self, *args, **kwargs): # little hack: # get_creation_fields is a class method but it needs to create # an instance, this hack avoids calls to default value functions if "__fake__" not in kwargs: super(ECR, self).__init__(*args, **kwargs) self._promotion_errors = None def __unicode__(self): return u"ECR<%s>" % self.reference @property def title(self): attrs = (esc(self.reference), esc(self.name)) return mark_safe( u'''<span class="type">ECR</span> // <span class="reference">%s</span> // <span class="name">%s</span>''' % attrs) def is_promotable(self): """ Returns True if the object's state is the last state of its lifecycle. """ self._promotion_errors = ErrorList() if self.lifecycle.last_state == self.state: self._promotion_errors.append( _(u"The object is at its last state.")) return False return True def _get_promotion_errors(self): """ Returns an :class:`.ErrorList` of promotion errors. Calls :meth:`.is_promotable()` if it has not already been called. """ if self._promotion_errors is None: self.is_promotable() return self._promotion_errors promotion_errors = property(_get_promotion_errors) @property def is_cloneable(self): """ """ return False @property def is_editable(self): """ True if the object is not in a non editable state """ return self.is_draft and not self.approvals.now().exists() @property @pmodels.cache_lifecycle_stuff def is_proposed(self): """ True if the object is in a state prior to the official state but not draft. """ if self.is_cancelled or self.is_draft: return False lcs = self.lifecycle.lifecyclestates_set.only("rank") current_rank = lcs.get(state=self.state).rank official_rank = lcs.get(state=self.lifecycle.official_state).rank return current_rank < official_rank @property @pmodels.cache_lifecycle_stuff def is_cancelled(self): """ True if the object is cancelled. """ return self.lifecycle == pmodels.get_cancelled_lifecycle() @property @pmodels.cache_lifecycle_stuff def is_deprecated(self): """ Always returns False since an ECR can not be deprecated""" return False @property @pmodels.cache_lifecycle_stuff def is_official(self): u"Returns True if object is official." "" return not self.is_cancelled and self.state == self.lifecycle.official_state @property @pmodels.cache_lifecycle_stuff def is_draft(self): u""" Returns True if the object is a draft. """ return not self.is_cancelled and self.state == self.lifecycle.first_state @pmodels.cache_lifecycle_stuff def get_current_sign_level(self): """ Returns the current sign level that a user must have to promote this object. """ rank = pmodels.LifecycleStates.objects.get( state=self.state, lifecycle=self.lifecycle).rank return level_to_sign_str(rank) @pmodels.cache_lifecycle_stuff def get_previous_sign_level(self): """ Returns the current sign level that a user must have to demote this object. """ rank = pmodels.LifecycleStates.objects.get( state=self.state, lifecycle=self.lifecycle).rank return level_to_sign_str(rank - 1) @property def attributes(self): u"Attributes to display in `Attributes view`" return [ "reference", "name", "description", "creator", "owner", "ctime", "mtime" ] @property def menu_items(self): "Menu items to choose a view" return [ ugettext_noop("attributes"), ugettext_noop("lifecycle"), ugettext_noop("history"), ugettext_noop("part-doc-cads"), ] @property def plmobject_url(self): return iri_to_uri(u"/ecr/%s/" % self.reference) @classmethod def get_creation_fields(cls): """ Returns fields which should be displayed in a creation form. """ return ["name", "reference", "description", "lifecycle"] @classmethod def get_modification_fields(cls): """ Returns fields which should be displayed in a modification form """ return ["name", "description"] def get_current_signer_role(self): lcl = self.lifecycle.to_states_list() return level_to_sign_str(lcl.index(self.state.name)) def get_current_signers(self): role = self.get_current_signer_role() return self.users.now().filter(role=role).values_list("user", flat=True) def get_approvers(self): if self.is_official or self.is_cancelled: return self.approvals.none() lcl = self.lifecycle.to_states_list() next_state = lcl.next_state(self.state.name) approvers = self.approvals.now().filter( current_state=self.state, next_state=next_state).values_list("user", flat=True) return approvers @property def is_part(self): return False @property def is_document(self): return False @property def type(self): return "ECR"
def set_connection_error(self): errorList = ErrorList() errorList.append('User not found') self._errors = { 'username': errorList }
class PLMObject(AbstractPLMObject): u""" Base class for :class:`.Part` and :class:`.Document`. A PLMObject is identified by a triplet reference/type/revision :key attributes: .. attribute:: reference Reference of the :class:`.PLMObject`, for example ``YLTG00`` .. attribute:: type Type of the :class:`.PLMObject`, for example ``Game`` .. attribute:: revision Revision of the :class:`.PLMObject`, for example ``a`` :other attributes: .. attribute:: name Name of the product, for example ``Game of life`` .. attribute:: creator :class:`~django.contrib.auth.models.User` who created the :class:`.PLMObject` .. attribute:: creator :class:`~django.contrib.auth.models.User` who owns the :class:`.PLMObject` .. attribute:: ctime date of creation of the object (default value : current time) .. attribute:: mtime date of last modification of the object (automatically field at each save) .. attribute:: lifecycle :class:`.Lifecycle` of the object .. attribute:: state Current :class:`.State` of the object .. attribute:: group :class:`.GroupInfo` that owns the object .. attribute:: published .. versionadded:: 1.1 True if the object is published (accessible to anonymous user) .. attribute:: reference_number .. versionadded:: 1.1 number found in the reference if it matches ``PART_|DOC_\d+`` .. attribute:: description .. versionadded:: 2.0 a short description of the object. This field is optional and is a richtext field. .. note:: This class is abstract, to create a PLMObject, see :class:`.Part` and :class:`.Document`. .. versionchanged:: 1.1 :attr:`.published` and :attr:`.reference_number` added. """ # key attributes reference = models.CharField( _("reference"), max_length=50, db_index=True, help_text= _(u"Required. 50 characters or fewer. Letters, numbers , except #, ?, / and .. characters" )) type = models.CharField(_("type"), max_length=50) revision = models.CharField(_("revision"), max_length=50) # hidden field to get a valid new reference reference_number = models.IntegerField(default=0) # other attributes name = models.CharField(_("name"), max_length=100, blank=True, help_text=_(u"Name of the product")) description = models.TextField(_("description"), blank=True, default="") description.richtext = True creator = models.ForeignKey(User, verbose_name=_("creator"), related_name="%(class)s_creator") owner = models.ForeignKey(User, verbose_name=_("owner"), related_name="%(class)s_owner") ctime = models.DateTimeField(_("date of creation"), default=timezone.now, auto_now_add=False) mtime = models.DateTimeField(_("date of last modification"), auto_now=True) group = models.ForeignKey(GroupInfo, verbose_name=_("group"), related_name="%(class)s_group") # state and lifecycle lifecycle = models.ForeignKey(Lifecycle, verbose_name=_("lifecycle"), related_name="+", default=get_default_lifecycle) state = models.ForeignKey(State, verbose_name=_("state"), related_name="+", default=get_default_state) published = models.BooleanField(verbose_name=_("published"), default=False) class Meta: # keys in the database app_label = "plmapp" unique_together = (('reference', 'type', 'revision'), ) ordering = ["type", "reference", "revision"] def __init__(self, *args, **kwargs): # little hack: # get_creation_fields is a class method but it needs to create # an instance, this hack avoids calls to default value functions if "__fake__" not in kwargs: super(PLMObject, self).__init__(*args, **kwargs) self._promotion_errors = None self._title = None self._plmobject_url = None def __unicode__(self): return u"%s<%s/%s/%s>" % (type(self).__name__, self.reference, self.type, self.revision) @property def title(self): if self._title is None: attrs = tuple( esc(x) for x in [self.name, self.type, self.reference, self.revision]) self._title = mark_safe( u'''<span class="name">%s</span> (<span class="type">%s</span> // <span class="reference">%s</span> // <span class="revision">%s</span>)''' % attrs) return self._title def _is_promotable(self): """ Returns True if the object's state is the last state of its lifecycle. """ self._promotion_errors = ErrorList() if self.lifecycle.last_state == self.state: self._promotion_errors.append( _(u"The object is at its last state.")) return False return True def is_promotable(self): u""" Returns True if object is promotable .. note:: This method is abstract and raises :exc:`.NotImplementedError`. This method must be overriden. """ raise NotImplementedError() def _get_promotion_errors(self): """ Returns an :class:`.ErrorList` of promotion errors. Calls :meth:`.is_promotable()` if it has not already been called. """ if self._promotion_errors is None: self.is_promotable() return self._promotion_errors promotion_errors = property(_get_promotion_errors) @property def is_cloneable(self): """ .. versionadded:: 1.1 Return true by default. This property may be overriden by custom Part or Document """ return True @property def is_editable(self): """ True if the object is not in a non editable state """ return self.is_draft and not self.approvals.now().exists() @property @cache_lifecycle_stuff def is_proposed(self): """ True if the object is in a state prior to the official state but not draft. """ if self.is_cancelled or self.is_draft: return False lcs = self.lifecycle.lifecyclestates_set.only("rank") current_rank = lcs.get(state=self.state).rank official_rank = lcs.get(state=self.lifecycle.official_state).rank return current_rank < official_rank @property @cache_lifecycle_stuff def is_cancelled(self): """ True if the object is cancelled. """ return self.lifecycle == get_cancelled_lifecycle() @property @cache_lifecycle_stuff def is_deprecated(self): """ True if the object is deprecated. """ return not self.is_cancelled and self.state == self.lifecycle.last_state @property @cache_lifecycle_stuff def is_official(self): u"Returns True if object is official." "" return not self.is_cancelled and self.state == self.lifecycle.official_state @property @cache_lifecycle_stuff def is_draft(self): u""" Returns True if the object is a draft. """ return not self.is_cancelled and self.state == self.lifecycle.first_state @cache_lifecycle_stuff def get_current_sign_level(self): """ Returns the current sign level that a user must have to promote this object. """ rank = LifecycleStates.objects.get(state=self.state, lifecycle=self.lifecycle).rank return level_to_sign_str(rank) @cache_lifecycle_stuff def get_previous_sign_level(self): """ Returns the current sign level that a user must have to demote this object. """ rank = LifecycleStates.objects.get(state=self.state, lifecycle=self.lifecycle).rank return level_to_sign_str(rank - 1) @property def is_part(self): """ True if the plmobject is a part.""" from openPLM.plmapp.models.part import Part if self.type in get_all_plmobjects(): return issubclass(get_all_plmobjects()[self.type], Part) return False @property def is_document(self): """ True if the plmobject is a document.""" from openPLM.plmapp.models.document import Document if self.type in get_all_plmobjects(): return issubclass(get_all_plmobjects()[self.type], Document) return False @property def attributes(self): u"Attributes to display in `Attributes view`" return [ "type", "reference", "revision", "name", "description", "creator", "owner", "group", "ctime", "mtime" ] @property def published_attributes(self): u""".. versionadded:: 1.1 Attributes that are visible to everyone if the object has been published.""" return [ "type", "reference", "revision", "name", ] @property def menu_items(self): "Menu items to choose a view" return [ ugettext_noop("attributes"), ugettext_noop("lifecycle"), ugettext_noop("revisions"), ugettext_noop("history"), ] @classmethod def excluded_creation_fields(cls): "Returns fields which should not be available in a creation form" return ["owner", "creator", "ctime", "mtime", "state"] @property def plmobject_url(self): if self._plmobject_url is None: url = u"/object/%s/%s/%s/" % (self.type, self.reference, self.revision) self._plmobject_url = iri_to_uri(url) return self._plmobject_url @classmethod def get_creation_fields(cls): """ Returns fields which should be displayed in a creation form. By default, it returns :attr:`.attributes` less attributes returned by :meth:`.excluded_creation_fields` """ fields = [ "name", "group", "reference", "type", "revision", "lifecycle", "description" ] excludes = cls.excluded_creation_fields() for field in cls(__fake__=True).attributes: if field not in excludes and field not in fields: fields.insert(2, field) return fields @classmethod def excluded_modification_fields(cls): """ Returns fields which should not be available in a modification form """ return [ ugettext_noop("type"), ugettext_noop("reference"), ugettext_noop("revision"), ugettext_noop("ctime"), ugettext_noop("creator"), ugettext_noop("owner"), ugettext_noop("ctime"), ugettext_noop("mtime"), ugettext_noop("group") ] @classmethod def get_modification_fields(cls): """ Returns fields which should be displayed in a modification form By default, it returns :attr:`.attributes` less attributes returned by :meth:`.excluded_modification_fields` """ fields = [] for field in cls(__fake__=True).attributes: if field not in cls.excluded_modification_fields(): fields.append(field) return fields def get_leaf_object(self): return get_all_plmobjects()[self.type].objects.get(id=self.id) def get_current_signer_role(self): lcl = self.lifecycle.to_states_list() return level_to_sign_str(lcl.index(self.state.name)) def get_current_signers(self): role = self.get_current_signer_role() return self.users.now().filter(role=role).values_list("user", flat=True) def get_approvers(self): if self.is_deprecated or self.is_cancelled: return self.approvals.none() lcl = self.lifecycle.to_states_list() next_state = lcl.next_state(self.state.name) approvers = self.approvals.now().filter( current_state=self.state, next_state=next_state).values_list("user", flat=True) return approvers
class ECR(models.Model, pmodels.IObject): u""" ECR (Engineering Change Request) model. :key attributes: .. attribute:: reference Reference of the :class:`.ECR`, for example ``ECR_0001`` :other attributes: .. attribute:: name Name of the ECR, for example ``Game of life`` .. attribute:: description long description of the ECR .. attribute:: creator :class:`~django.contrib.auth.models.User` who created the :class:`.ECR` .. attribute:: creator :class:`~django.contrib.auth.models.User` who owns the :class:`.ECR` .. attribute:: ctime date of creation of the object (default value : current time) .. attribute:: mtime date of last modification of the object (automatically field at each save) .. attribute:: lifecycle :class:`.Lifecycle` of the object .. attribute:: state Current :class:`.State` of the object .. attribute:: reference_number number found in the reference if it matches ``ECR_\d+`` """ # key attributes reference = models.CharField(_("reference"), max_length=50, db_index=True, unique=True, help_text=_(u"Required. 50 characters or fewer. Letters, numbers , except #, ?, / and .. characters")) # hidden field to get a valid new reference reference_number = models.IntegerField(default=0) # other attributes name = models.CharField(_("name"), max_length=100, blank=True, help_text=_(u"Name of the ECR")) description = models.TextField(_("description"), blank=True) description.richtext = True creator = models.ForeignKey(User, verbose_name=_("creator"), related_name="%(class)s_creator") owner = models.ForeignKey(User, verbose_name=_("owner"), related_name="%(class)s_owner") ctime = models.DateTimeField(_("date of creation"), default=timezone.now, auto_now_add=False) mtime = models.DateTimeField(_("date of last modification"), auto_now=True) # state and lifecycle lifecycle = models.ForeignKey(pmodels.Lifecycle, verbose_name=_("lifecycle"), related_name="+",) state = models.ForeignKey(pmodels.State, verbose_name=_("state"), related_name="+",) class Meta: # keys in the database ordering = ["reference"] def __init__(self, *args, **kwargs): # little hack: # get_creation_fields is a class method but it needs to create # an instance, this hack avoids calls to default value functions if "__fake__" not in kwargs: super(ECR, self).__init__(*args, **kwargs) self._promotion_errors = None def __unicode__(self): return u"ECR<%s>" % self.reference @property def title(self): attrs = (esc(self.reference), esc(self.name)) return mark_safe(u'''<span class="type">ECR</span> // <span class="reference">%s</span> // <span class="name">%s</span>''' % attrs) def is_promotable(self): """ Returns True if the object's state is the last state of its lifecycle. """ self._promotion_errors = ErrorList() if self.lifecycle.last_state == self.state: self._promotion_errors.append(_(u"The object is at its last state.")) return False return True def _get_promotion_errors(self): """ Returns an :class:`.ErrorList` of promotion errors. Calls :meth:`.is_promotable()` if it has not already been called. """ if self._promotion_errors is None: self.is_promotable() return self._promotion_errors promotion_errors = property(_get_promotion_errors) @property def is_cloneable(self): """ """ return False @property def is_editable(self): """ True if the object is not in a non editable state """ return self.is_draft and not self.approvals.now().exists() @property @pmodels.cache_lifecycle_stuff def is_proposed(self): """ True if the object is in a state prior to the official state but not draft. """ if self.is_cancelled or self.is_draft: return False lcs = self.lifecycle.lifecyclestates_set.only("rank") current_rank = lcs.get(state=self.state).rank official_rank = lcs.get(state=self.lifecycle.official_state).rank return current_rank < official_rank @property @pmodels.cache_lifecycle_stuff def is_cancelled(self): """ True if the object is cancelled. """ return self.lifecycle == pmodels.get_cancelled_lifecycle() @property @pmodels.cache_lifecycle_stuff def is_deprecated(self): """ Always returns False since an ECR can not be deprecated""" return False @property @pmodels.cache_lifecycle_stuff def is_official(self): u"Returns True if object is official.""" return not self.is_cancelled and self.state == self.lifecycle.official_state @property @pmodels.cache_lifecycle_stuff def is_draft(self): u""" Returns True if the object is a draft. """ return not self.is_cancelled and self.state == self.lifecycle.first_state @pmodels.cache_lifecycle_stuff def get_current_sign_level(self): """ Returns the current sign level that a user must have to promote this object. """ rank = pmodels.LifecycleStates.objects.get(state=self.state, lifecycle=self.lifecycle).rank return level_to_sign_str(rank) @pmodels.cache_lifecycle_stuff def get_previous_sign_level(self): """ Returns the current sign level that a user must have to demote this object. """ rank = pmodels.LifecycleStates.objects.get(state=self.state, lifecycle=self.lifecycle).rank return level_to_sign_str(rank - 1) @property def attributes(self): u"Attributes to display in `Attributes view`" return ["reference", "name", "description", "creator", "owner", "ctime", "mtime"] @property def menu_items(self): "Menu items to choose a view" return [ugettext_noop("attributes"), ugettext_noop("lifecycle"), ugettext_noop("history"), ugettext_noop("part-doc-cads"), ] @property def plmobject_url(self): return iri_to_uri(u"/ecr/%s/" % self.reference) @classmethod def get_creation_fields(cls): """ Returns fields which should be displayed in a creation form. """ return ["name", "reference", "description", "lifecycle"] @classmethod def get_modification_fields(cls): """ Returns fields which should be displayed in a modification form """ return ["name", "description"] def get_current_signer_role(self): lcl = self.lifecycle.to_states_list() return level_to_sign_str(lcl.index(self.state.name)) def get_current_signers(self): role = self.get_current_signer_role() return self.users.now().filter(role=role).values_list("user", flat=True) def get_approvers(self): if self.is_official or self.is_cancelled: return self.approvals.none() lcl = self.lifecycle.to_states_list() next_state = lcl.next_state(self.state.name) approvers = self.approvals.now().filter(current_state=self.state, next_state=next_state).values_list("user", flat=True) return approvers @property def is_part(self): return False @property def is_document(self): return False @property def type(self): return "ECR"
def _createError(self,key,error_message): errorList = ErrorList() errorList.append(error_message) self.extras[key] = errorList
class PLMObject(models.Model): u""" Base class for :class:`Part` and :class:`Document`. A PLMObject is identified by a triplet reference/type/revision :key attributes: .. attribute:: reference Reference of the :class:`PLMObject`, for example ``YLTG00`` .. attribute:: type Type of the :class:`PLMObject`, for example ``Game`` .. attribute:: revision Revision of the :class:`PLMObject`, for example ``a`` :other attributes: .. attribute:: name Name of the product, for example ``Game of life`` .. attribute:: creator :class:`~django.contrib.auth.models.User` who created the :class:`PLMObject` .. attribute:: creator :class:`~django.contrib.auth.models.User` who owns the :class:`PLMObject` .. attribute:: ctime date of creation of the object (default value : current time) .. attribute:: mtime date of last modification of the object (automatically field at each save) .. attribute:: lifecycle :class:`Lifecycle` of the object .. attribute:: state Current :class:`State` of the object .. attribute:: group :class:`GroupInfo` that owns the object .. note:: This class is abstract, to create a PLMObject, see :class:`Part` and :class:`Document`. """ # key attributes reference = models.CharField(_("reference"), max_length=50, db_index=True) type = models.CharField(_("type"), max_length=50) revision = models.CharField(_("revision"), max_length=50) # other attributes name = models.CharField(_("name"), max_length=100, blank=True, help_text=_(u"Name of the product")) creator = models.ForeignKey(User, verbose_name=_("creator"), related_name="%(class)s_creator") owner = models.ForeignKey(User, verbose_name=_("owner"), related_name="%(class)s_owner") ctime = models.DateTimeField(_("date of creation"), default=datetime.datetime.today, auto_now_add=False) mtime = models.DateTimeField(_("date of last modification"), auto_now=True) group = models.ForeignKey(GroupInfo, related_name="%(class)s_group") # state and lifecycle lifecycle = models.ForeignKey(Lifecycle, verbose_name=_("lifecycle"), related_name="%(class)s_lifecyle", default=get_default_lifecycle) state = models.ForeignKey(State, verbose_name=_("state"), related_name="%(class)s_lifecyle", default=get_default_state) class Meta: # keys in the database unique_together = (('reference', 'type', 'revision'),) ordering = ["type", "reference", "revision"] def __init__(self, *args, **kwargs): # little hack: # get_creation_fields is a class method but it needs to create # an instance, this hacks avoids calls to default value functions if "__fake__" not in kwargs: super(PLMObject, self).__init__(*args, **kwargs) self._promotion_errors = None def __unicode__(self): return u"%s<%s/%s/%s>" % (type(self).__name__, self.reference, self.type, self.revision) def _is_promotable(self): """ Returns True if the object's state is the last state of its lifecycle. """ self._promotion_errors = ErrorList() if self.lifecycle.last_state == self.state: self._promotion_errors.append(_(u"The object is at its last state.")) return False return True def is_promotable(self): u""" Returns True if object is promotable .. note:: This method is abstract and raises :exc:`NotImplementedError`. This method must be overriden. """ raise NotImplementedError() def _get_promotion_errors(self): """ Returns an :class:`ErrorList` of promotion errors. Calls :meth:`is_promotable()` if it has not already been called. """ if self._promotion_errors is None: self.is_promotable() return self._promotion_errors promotion_errors = property(_get_promotion_errors) @property def is_editable(self): """ True if the object is not in a non editable state (for example, in an official or deprecated state). """ lcs = self.lifecycle.lifecyclestates_set.only("rank") current_rank = lcs.get(state=self.state).rank official_rank = lcs.get(state=self.lifecycle.official_state).rank return current_rank < official_rank def get_current_sign_level(self): """ Returns the current sign level that an user must have to promote this object. """ rank = LifecycleStates.objects.get(state=self.state, lifecycle=self.lifecycle).rank return level_to_sign_str(rank) def get_previous_sign_level(self): """ Returns the current sign level that an user must have to demote this object. """ rank = LifecycleStates.objects.get(state=self.state, lifecycle=self.lifecycle).rank return level_to_sign_str(rank - 1) @property def is_part(self): if self.type in get_all_plmobjects(): return issubclass(get_all_plmobjects()[self.type], Part) return False @property def is_document(self): if self.type in get_all_plmobjects(): return issubclass(get_all_plmobjects()[self.type], Document) return False @property def is_official(self): u"Returns True if document's state is official.""" return self.state == self.lifecycle.official_state @property def attributes(self): u"Attributes to display in `Attributes view`" return ["type", "reference", "revision", "name", "creator", "owner", "group", "ctime", "mtime"] @property def menu_items(self): "Menu items to choose a view" return [ugettext_noop("attributes"), ugettext_noop("lifecycle"), ugettext_noop("revisions"), ugettext_noop("history"), ugettext_noop("management")] @classmethod def excluded_creation_fields(cls): "Returns fields which should not be available in a creation form" return ["owner", "creator", "ctime", "mtime", "state"] @property def plmobject_url(self): url = u"/object/%s/%s/%s/" % (self.type, self.reference, self.revision) return iri_to_uri(url) @classmethod def get_creation_fields(cls): """ Returns fields which should be displayed in a creation form. By default, it returns :attr:`attributes` less attributes returned by :meth:`excluded_creation_fields` """ fields = ["reference", "type", "revision", "lifecycle"] for field in cls(__fake__=True).attributes: if field not in cls.excluded_creation_fields(): fields.append(field) return fields @classmethod def excluded_modification_fields(cls): """ Returns fields which should not be available in a modification form """ return [ugettext_noop("type"), ugettext_noop("reference"), ugettext_noop("revision"), ugettext_noop("ctime"), ugettext_noop("creator"), ugettext_noop("owner"), ugettext_noop("ctime"), ugettext_noop("mtime"), ugettext_noop("group")] @classmethod def get_modification_fields(cls): """ Returns fields which should be displayed in a modification form By default, it returns :attr:`attributes` less attributes returned by :meth:`excluded_modification_fields` """ fields = [] for field in cls(__fake__=True).attributes: if field not in cls.excluded_modification_fields(): fields.append(field) return fields def get_attributes_and_values(self): return [(attr, getattr(self, attr)) for attr in self.attributes] def get_leaf_object(self): return get_all_plmobjects()[self.type].objects.get(id=self.id)