#NEWLINE# def get_validation_errors( outfile , app = None ) : #NEWLINE# #INDENT# '\n    Validates all models that are part of the specified app. If no app name is provided,\n    validates all models of all installed apps. Writes errors, if any, to outfile.\n    Returns number of errors.\n    ' #NEWLINE# from django.conf import settings #NEWLINE# from django.db import models , connection #NEWLINE# from django.db.models.loading import get_app_errors #NEWLINE# from django.db.models.fields.related import RelatedObject #NEWLINE# e = ModelErrorCollection ( outfile ) #NEWLINE# for ( app_name , error ) in get_app_errors ( ) . items ( ) : #NEWLINE# #INDENT# e . add ( app_name , error ) #NEWLINE# #UNINDENT# for cls in models . get_models ( app ) : #NEWLINE# #INDENT# opts = cls . _meta #NEWLINE# for f in opts . local_fields : #NEWLINE# #INDENT# if ( ( f . name == 'id' ) and ( not f . primary_key ) and ( opts . pk . name == 'id' ) ) : #NEWLINE# #INDENT# e . add ( opts , ( '"%s": You can\'t use "id" as a field name, because each model automatically gets an "id" field if none of the fields have primary_key=True. You need to either remove/rename your "id" field or add primary_key=True to a field.' % f . name ) ) #NEWLINE# #UNINDENT# if f . name . endswith ( '_' ) : #NEWLINE# #INDENT# e . add ( opts , ( '"%s": Field names cannot end with underscores, because this would lead to ambiguous queryset filters.' % f . name ) ) #NEWLINE# #UNINDENT# if isinstance ( f , models . CharField ) : #NEWLINE# #INDENT# try : #NEWLINE# #INDENT# max_length = int ( f . max_length ) #NEWLINE# if ( max_length <= 0 ) : #NEWLINE# #INDENT# e . add ( opts , ( '"%s": CharFields require a "max_length" attribute that is a positive integer.' % f . name ) ) #NEWLINE# #UNINDENT# #UNINDENT# except ( ValueError , TypeError ) : #NEWLINE# #INDENT# e . add ( opts , ( '"%s": CharFields require a "max_length" attribute that is a positive integer.' % f . name ) ) #NEWLINE# #UNINDENT# #UNINDENT# if isinstance ( f , models . DecimalField ) : #NEWLINE# #INDENT# ( decimalp_ok , mdigits_ok ) = ( False , False ) #NEWLINE# decimalp_msg = '"%s": DecimalFields require a "decimal_places" attribute that is a non-negative integer.' #NEWLINE# try : #NEWLINE# #INDENT# decimal_places = int ( f . decimal_places ) #NEWLINE# if ( decimal_places < 0 ) : #NEWLINE# #INDENT# e . add ( opts , ( decimalp_msg % f . name ) ) #NEWLINE# #UNINDENT# else : #NEWLINE# #INDENT# decimalp_ok = True #NEWLINE# #UNINDENT# #UNINDENT# except ( ValueError , TypeError ) : #NEWLINE# #INDENT# e . add ( opts , ( decimalp_msg % f . name ) ) #NEWLINE# #UNINDENT# mdigits_msg = '"%s": DecimalFields require a "max_digits" attribute that is a positive integer.' #NEWLINE# try : #NEWLINE# #INDENT# max_digits = int ( f . max_digits ) #NEWLINE# if ( max_digits <= 0 ) : #NEWLINE# #INDENT# e . add ( opts , ( mdigits_msg % f . name ) ) #NEWLINE# #UNINDENT# else : #NEWLINE# #INDENT# mdigits_ok = True #NEWLINE# #UNINDENT# #UNINDENT# except ( ValueError , TypeError ) : #NEWLINE# #INDENT# e . add ( opts , ( mdigits_msg % f . name ) ) #NEWLINE# #UNINDENT# invalid_values_msg = '"%s": DecimalFields require a "max_digits" attribute value that is greater than the value of the "decimal_places" attribute.' #NEWLINE# if ( decimalp_ok and mdigits_ok ) : #NEWLINE# #INDENT# if ( decimal_places >= max_digits ) : #NEWLINE# #INDENT# e . add ( opts , ( invalid_values_msg % f . name ) ) #NEWLINE# #UNINDENT# #UNINDENT# #UNINDENT# if ( isinstance ( f , models . FileField ) and ( not f . upload_to ) ) : #NEWLINE# #INDENT# e . add ( opts , ( '"%s": FileFields require an "upload_to" attribute.' % f . name ) ) #NEWLINE# #UNINDENT# if isinstance ( f , models . ImageField ) : #NEWLINE# #INDENT# try : #NEWLINE# #INDENT# from PIL import Image #NEWLINE# #UNINDENT# except ImportError : #NEWLINE# #INDENT# try : #NEWLINE# #INDENT# import Image #NEWLINE# #UNINDENT# except ImportError : #NEWLINE# #INDENT# e . add ( opts , ( '"%s": To use ImageFields, you need to install the Python Imaging Library. Get it at http://www.pythonware.com/products/pil/ .' % f . name ) ) #NEWLINE# #UNINDENT# #UNINDENT# #UNINDENT# if ( isinstance ( f , models . BooleanField ) and getattr ( f , 'null' , False ) ) : #NEWLINE# #INDENT# e . add ( opts , ( '"%s": BooleanFields do not accept null values. Use a NullBooleanField instead.' % f . name ) ) #NEWLINE# #UNINDENT# if f . choices : #NEWLINE# #INDENT# if ( isinstance ( f . choices , basestring ) or ( not is_iterable ( f . choices ) ) ) : #NEWLINE# #INDENT# e . add ( opts , ( '"%s": "choices" should be iterable (e.g., a tuple or list).' % f . name ) ) #NEWLINE# #UNINDENT# else : #NEWLINE# #INDENT# for c in f . choices : #NEWLINE# #INDENT# if ( ( not isinstance ( c , ( list , tuple ) ) ) or ( len ( c ) != 2 ) ) : #NEWLINE# #INDENT# e . add ( opts , ( '"%s": "choices" should be a sequence of two-tuples.' % f . name ) ) #NEWLINE# #UNINDENT# #UNINDENT# #UNINDENT# #UNINDENT# if ( f . db_index not in ( None , True , False ) ) : #NEWLINE# #INDENT# e . add ( opts , ( '"%s": "db_index" should be either None, True or False.' % f . name ) ) #NEWLINE# #UNINDENT# connection . validation . validate_field ( e , opts , f ) #NEWLINE# if f . rel : #NEWLINE# #INDENT# if ( f . rel . to not in models . get_models ( ) ) : #NEWLINE# #INDENT# e . add ( opts , ( "'%s' has a relation with model %s, which has either not been installed or is abstract." % ( f . name , f . rel . to ) ) ) #NEWLINE# #UNINDENT# if isinstance ( f . rel . to , ( str , unicode ) ) : #NEWLINE# #INDENT# continue #NEWLINE# #UNINDENT# if ( not f . rel . to . _meta . get_field ( f . rel . field_name ) . unique ) : #NEWLINE# #INDENT# e . add ( opts , ( "Field '%s' under model '%s' must have a unique=True constraint." % ( f . rel . field_name , f . rel . to . __name__ ) ) ) #NEWLINE# #UNINDENT# rel_opts = f . rel . to . _meta #NEWLINE# rel_name = RelatedObject ( f . rel . to , cls , f ) . get_accessor_name ( ) #NEWLINE# rel_query_name = f . related_query_name ( ) #NEWLINE# if ( not f . rel . is_hidden ( ) ) : #NEWLINE# #INDENT# for r in rel_opts . fields : #NEWLINE# #INDENT# if ( r . name == rel_name ) : #NEWLINE# #INDENT# e . add ( opts , ( "Accessor for field '%s' clashes with field '%s.%s'. Add a related_name argument to the definition for '%s'." % ( f . name , rel_opts . object_name , r . name , f . name ) ) ) #NEWLINE# #UNINDENT# if ( r . name == rel_query_name ) : #NEWLINE# #INDENT# e . add ( opts , ( "Reverse query name for field '%s' clashes with field '%s.%s'. Add a related_name argument to the definition for '%s'." % ( f . name , rel_opts . object_name , r . name , f . name ) ) ) #NEWLINE# #UNINDENT# #UNINDENT# for r in rel_opts . local_many_to_many : #NEWLINE# #INDENT# if ( r . name == rel_name ) : #NEWLINE# #INDENT# e . add ( opts , ( "Accessor for field '%s' clashes with m2m field '%s.%s'. Add a related_name argument to the definition for '%s'." % ( f . name , rel_opts . object_name , r . name , f . name ) ) ) #NEWLINE# #UNINDENT# if ( r . name == rel_query_name ) : #NEWLINE# #INDENT# e . add ( opts , ( "Reverse query name for field '%s' clashes with m2m field '%s.%s'. Add a related_name argument to the definition for '%s'." % ( f . name , rel_opts . object_name , r . name , f . name ) ) ) #NEWLINE# #UNINDENT# #UNINDENT# for r in rel_opts . get_all_related_many_to_many_objects ( ) : #NEWLINE# #INDENT# if ( r . get_accessor_name ( ) == rel_name ) : #NEWLINE# #INDENT# e . add ( opts , ( "Accessor for field '%s' clashes with related m2m field '%s.%s'. Add a related_name argument to the definition for '%s'." % ( f . name , rel_opts . object_name , r . get_accessor_name ( ) , f . name ) ) ) #NEWLINE# #UNINDENT# if ( r . get_accessor_name ( ) == rel_query_name ) : #NEWLINE# #INDENT# e . add ( opts , ( "Reverse query name for field '%s' clashes with related m2m field '%s.%s'. Add a related_name argument to the definition for '%s'." % ( f . name , rel_opts . object_name , r . get_accessor_name ( ) , rel_to . name ) ) ) #NEWLINE# #UNINDENT# #UNINDENT# for r in rel_opts . get_all_related_objects ( ) : #NEWLINE# #INDENT# if ( r . field is not f ) : #NEWLINE# #INDENT# if ( r . get_accessor_name ( ) == rel_name ) : #NEWLINE# #INDENT# e . add ( opts , ( "Accessor for field '%s' clashes with related field '%s.%s'. Add a related_name argument to the definition for '%s'." % ( f . name , rel_opts . object_name , r . get_accessor_name ( ) , f . name ) ) ) #NEWLINE# #UNINDENT# if ( r . get_accessor_name ( ) == rel_query_name ) : #NEWLINE# #INDENT# e . add ( opts , ( "Reverse query name for field '%s' clashes with related field '%s.%s'. Add a related_name argument to the definition for '%s'." % ( f . name , rel_opts . object_name , r . get_accessor_name ( ) , f . name ) ) ) #NEWLINE# #UNINDENT# #UNINDENT# #UNINDENT# #UNINDENT# #UNINDENT# #UNINDENT# seen_intermediary_signatures = [ ] #NEWLINE# for ( i , f ) in enumerate ( opts . local_many_to_many ) : #NEWLINE# #INDENT# if ( f . rel . to not in models . get_models ( ) ) : #NEWLINE# #INDENT# e . add ( opts , ( "'%s' has an m2m relation with model %s, which has either not been installed or is abstract." % ( f . name , f . rel . to ) ) ) #NEWLINE# if isinstance ( f . rel . to , ( str , unicode ) ) : #NEWLINE# #INDENT# continue #NEWLINE# #UNINDENT# #UNINDENT# if f . unique : #NEWLINE# #INDENT# e . add ( opts , ( "ManyToManyFields cannot be unique.  Remove the unique argument on '%s'." % f . name ) ) #NEWLINE# #UNINDENT# if ( ( f . rel . through is not None ) and ( not isinstance ( f . rel . through , basestring ) ) ) : #NEWLINE# #INDENT# ( from_model , to_model ) = ( cls , f . rel . to ) #NEWLINE# if ( ( from_model == to_model ) and f . rel . symmetrical and ( not f . rel . through . _meta . auto_created ) ) : #NEWLINE# #INDENT# e . add ( opts , 'Many-to-many fields with intermediate tables cannot be symmetrical.' ) #NEWLINE# #UNINDENT# ( seen_from , seen_to , seen_self ) = ( False , False , 0 ) #NEWLINE# for inter_field in f . rel . through . _meta . fields : #NEWLINE# #INDENT# rel_to = getattr ( inter_field . rel , 'to' , None ) #NEWLINE# if ( from_model == to_model ) : #NEWLINE# #INDENT# if ( rel_to == from_model ) : #NEWLINE# #INDENT# seen_self += 1 #NEWLINE# #UNINDENT# if ( seen_self > 2 ) : #NEWLINE# #INDENT# e . add ( opts , ( 'Intermediary model %s has more than two foreign keys to %s, which is ambiguous and is not permitted.' % ( f . rel . through . _meta . object_name , from_model . _meta . object_name ) ) ) #NEWLINE# #UNINDENT# #UNINDENT# else : #NEWLINE# #INDENT# if ( rel_to == from_model ) : #NEWLINE# #INDENT# if seen_from : #NEWLINE# #INDENT# e . add ( opts , ( 'Intermediary model %s has more than one foreign key to %s, which is ambiguous and is not permitted.' % ( f . rel . through . _meta . object_name , from_model . _meta . object_name ) ) ) #NEWLINE# #UNINDENT# else : #NEWLINE# #INDENT# seen_from = True #NEWLINE# #UNINDENT# #UNINDENT# else : #NEWLINE# #INDENT# if ( rel_to == to_model ) : #NEWLINE# #INDENT# if seen_to : #NEWLINE# #INDENT# e . add ( opts , ( 'Intermediary model %s has more than one foreign key to %s, which is ambiguous and is not permitted.' % ( f . rel . through . _meta . object_name , rel_to . _meta . object_name ) ) ) #NEWLINE# #UNINDENT# else : #NEWLINE# #INDENT# seen_to = True #NEWLINE# #UNINDENT# #UNINDENT# #UNINDENT# #UNINDENT# #UNINDENT# if ( f . rel . through not in models . get_models ( include_auto_created = True ) ) : #NEWLINE# #INDENT# e . add ( opts , ( "'%s' specifies an m2m relation through model %s, which has not been installed." % ( f . name , f . rel . through ) ) ) #NEWLINE# #UNINDENT# signature = ( f . rel . to , cls , f . rel . through ) #NEWLINE# if ( signature in seen_intermediary_signatures ) : #NEWLINE# #INDENT# e . add ( opts , ( 'The model %s has two manually-defined m2m relations through the model %s, which is not permitted. Please consider using an extra field on your intermediary model instead.' % ( cls . _meta . object_name , f . rel . through . _meta . object_name ) ) ) #NEWLINE# #UNINDENT# else : #NEWLINE# #INDENT# seen_intermediary_signatures . append ( signature ) #NEWLINE# #UNINDENT# if ( not f . rel . through . _meta . auto_created ) : #NEWLINE# #INDENT# ( seen_related_fk , seen_this_fk ) = ( False , False ) #NEWLINE# for field in f . rel . through . _meta . fields : #NEWLINE# #INDENT# if field . rel : #NEWLINE# #INDENT# if ( ( not seen_related_fk ) and ( field . rel . to == f . rel . to ) ) : #NEWLINE# #INDENT# seen_related_fk = True #NEWLINE# #UNINDENT# else : #NEWLINE# #INDENT# if ( field . rel . to == cls ) : #NEWLINE# #INDENT# seen_this_fk = True #NEWLINE# #UNINDENT# #UNINDENT# #UNINDENT# #UNINDENT# if ( ( not seen_related_fk ) or ( not seen_this_fk ) ) : #NEWLINE# #INDENT# e . add ( opts , ( "'%s' is a manually-defined m2m relation through model %s, which does not have foreign keys to %s and %s" % ( f . name , f . rel . through . _meta . object_name , f . rel . to . _meta . object_name , cls . _meta . object_name ) ) ) #NEWLINE# #UNINDENT# #UNINDENT# #UNINDENT# else : #NEWLINE# #INDENT# if isinstance ( f . rel . through , basestring ) : #NEWLINE# #INDENT# e . add ( opts , ( "'%s' specifies an m2m relation through model %s, which has not been installed" % ( f . name , f . rel . through ) ) ) #NEWLINE# #UNINDENT# else : #NEWLINE# #INDENT# if isinstance ( f , GenericRelation ) : #NEWLINE# #INDENT# if ( not any ( [ isinstance ( vfield , GenericForeignKey ) for vfield in f . rel . to . _meta . virtual_fields ] ) ) : #NEWLINE# #INDENT# e . add ( opts , ( "Model '%s' must have a GenericForeignKey in order to create a GenericRelation that points to it." % f . rel . to . __name__ ) ) #NEWLINE# #UNINDENT# #UNINDENT# #UNINDENT# #UNINDENT# rel_opts = f . rel . to . _meta #NEWLINE# rel_name = RelatedObject ( f . rel . to , cls , f ) . get_accessor_name ( ) #NEWLINE# rel_query_name = f . related_query_name ( ) #NEWLINE# if ( rel_name is not None ) : #NEWLINE# #INDENT# for r in rel_opts . fields : #NEWLINE# #INDENT# if ( r . name == rel_name ) : #NEWLINE# #INDENT# e . add ( opts , ( "Accessor for m2m field '%s' clashes with field '%s.%s'. Add a related_name argument to the definition for '%s'." % ( f . name , rel_opts . object_name , r . name , f . name ) ) ) #NEWLINE# #UNINDENT# if ( r . name == rel_query_name ) : #NEWLINE# #INDENT# e . add ( opts , ( "Reverse query name for m2m field '%s' clashes with field '%s.%s'. Add a related_name argument to the definition for '%s'." % ( f . name , rel_opts . object_name , r . name , f . name ) ) ) #NEWLINE# #UNINDENT# #UNINDENT# for r in rel_opts . local_many_to_many : #NEWLINE# #INDENT# if ( r . name == rel_name ) : #NEWLINE# #INDENT# e . add ( opts , ( "Accessor for m2m field '%s' clashes with m2m field '%s.%s'. Add a related_name argument to the definition for '%s'." % ( f . name , rel_opts . object_name , r . name , f . name ) ) ) #NEWLINE# #UNINDENT# if ( r . name == rel_query_name ) : #NEWLINE# #INDENT# e . add ( opts , ( "Reverse query name for m2m field '%s' clashes with m2m field '%s.%s'. Add a related_name argument to the definition for '%s'." % ( f . name , rel_opts . object_name , r . name , f . name ) ) ) #NEWLINE# #UNINDENT# #UNINDENT# for r in rel_opts . get_all_related_many_to_many_objects ( ) : #NEWLINE# #INDENT# if ( r . field is not f ) : #NEWLINE# #INDENT# if ( r . get_accessor_name ( ) == rel_name ) : #NEWLINE# #INDENT# e . add ( opts , ( "Accessor for m2m field '%s' clashes with related m2m field '%s.%s'. Add a related_name argument to the definition for '%s'." % ( f . name , rel_opts . object_name , r . get_accessor_name ( ) , f . name ) ) ) #NEWLINE# #UNINDENT# if ( r . get_accessor_name ( ) == rel_query_name ) : #NEWLINE# #INDENT# e . add ( opts , ( "Reverse query name for m2m field '%s' clashes with related m2m field '%s.%s'. Add a related_name argument to the definition for '%s'." % ( f . name , rel_opts . object_name , r . get_accessor_name ( ) , f . name ) ) ) #NEWLINE# #UNINDENT# #UNINDENT# #UNINDENT# for r in rel_opts . get_all_related_objects ( ) : #NEWLINE# #INDENT# if ( r . get_accessor_name ( ) == rel_name ) : #NEWLINE# #INDENT# e . add ( opts , ( "Accessor for m2m field '%s' clashes with related field '%s.%s'. Add a related_name argument to the definition for '%s'." % ( f . name , rel_opts . object_name , r . get_accessor_name ( ) , f . name ) ) ) #NEWLINE# #UNINDENT# if ( r . get_accessor_name ( ) == rel_query_name ) : #NEWLINE# #INDENT# e . add ( opts , ( "Reverse query name for m2m field '%s' clashes with related field '%s.%s'. Add a related_name argument to the definition for '%s'." % ( f . name , rel_opts . object_name , r . get_accessor_name ( ) , f . name ) ) ) #NEWLINE# #UNINDENT# #UNINDENT# #UNINDENT# #UNINDENT# if opts . ordering : #NEWLINE# #INDENT# for field_name in opts . ordering : #NEWLINE# #INDENT# if ( field_name == '?' ) : #NEWLINE# #INDENT# continue #NEWLINE# #UNINDENT# if field_name . startswith ( '-' ) : #NEWLINE# #INDENT# field_name = field_name [ 1 : ] #NEWLINE# #UNINDENT# if ( opts . order_with_respect_to and ( field_name == '_order' ) ) : #NEWLINE# #INDENT# continue #NEWLINE# #UNINDENT# if ( '__' in field_name ) : #NEWLINE# #INDENT# continue #NEWLINE# #UNINDENT# try : #NEWLINE# #INDENT# opts . get_field ( field_name , many_to_many = False ) #NEWLINE# #UNINDENT# except models . FieldDoesNotExist : #NEWLINE# #INDENT# e . add ( opts , ( '"ordering" refers to "%s", a field that doesn\'t exist.' % field_name ) ) #NEWLINE# #UNINDENT# #UNINDENT# #UNINDENT# for ut in opts . unique_together : #NEWLINE# #INDENT# for field_name in ut : #NEWLINE# #INDENT# try : #NEWLINE# #INDENT# f = opts . get_field ( field_name , many_to_many = True ) #NEWLINE# #UNINDENT# except models . FieldDoesNotExist : #NEWLINE# #INDENT# e . add ( opts , ( '"unique_together" refers to %s, a field that doesn\'t exist. Check your syntax.' % field_name ) ) #NEWLINE# #UNINDENT# else : #NEWLINE# #INDENT# if isinstance ( f . rel , models . ManyToManyRel ) : #NEWLINE# #INDENT# e . add ( opts , ( '"unique_together" refers to %s. ManyToManyFields are not supported in unique_together.' % f . name ) ) #NEWLINE# #UNINDENT# if ( f not in opts . local_fields ) : #NEWLINE# #INDENT# e . add ( opts , ( '"unique_together" refers to %s. This is not in the same model as the unique_together statement.' % f . name ) ) #NEWLINE# #UNINDENT# #UNINDENT# #UNINDENT# #UNINDENT# #UNINDENT# return len ( e . errors )